seeddms-code/styles/bootstrap/cytoscape/cytoscape.js
2018-12-03 07:39:51 +01:00

29941 lines
770 KiB
JavaScript

(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["cytoscape"] = factory();
else
root["cytoscape"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 20);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/*global HTMLElement DocumentTouch */
var window = __webpack_require__(3);
var navigator = window ? window.navigator : null;
var document = window ? window.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 && is.fn(obj.instanceString) ? obj.instanceString() : null;
};
var is = {
defined: function defined(obj) {
return obj != null; // not undefined or null
},
string: function string(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) == typeofstr;
},
fn: function fn(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === typeoffn;
},
array: function array(obj) {
return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;
},
plainObject: function plainObject(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === typeofobj && !is.array(obj) && obj.constructor === Object;
},
object: function object(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === typeofobj;
},
number: function number(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === _typeof(1) && !isNaN(obj);
},
integer: function integer(obj) {
return is.number(obj) && Math.floor(obj) === obj;
},
bool: function bool(obj) {
return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === _typeof(true);
},
htmlElement: function htmlElement(obj) {
if ('undefined' === typeofhtmlele) {
return undefined;
} else {
return null != obj && obj instanceof HTMLElement;
}
},
elementOrCollection: function elementOrCollection(obj) {
return is.element(obj) || is.collection(obj);
},
element: function element(obj) {
return instanceStr(obj) === 'collection' && obj._private.single;
},
collection: function collection(obj) {
return instanceStr(obj) === 'collection' && !obj._private.single;
},
core: function core(obj) {
return instanceStr(obj) === 'core';
},
style: function style(obj) {
return instanceStr(obj) === 'style';
},
stylesheet: function stylesheet(obj) {
return instanceStr(obj) === 'stylesheet';
},
event: function event(obj) {
return instanceStr(obj) === 'event';
},
thread: function thread(obj) {
return instanceStr(obj) === 'thread';
},
fabric: function fabric(obj) {
return instanceStr(obj) === 'fabric';
},
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
},
nonemptyString: function nonemptyString(obj) {
if (obj && is.string(obj) && obj !== '' && !obj.match(/^\s+$/)) {
return true;
}
return false;
},
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;
}
},
boundingBox: function boundingBox(obj) {
return is.plainObject(obj) && is.number(obj.x1) && is.number(obj.x2) && is.number(obj.y1) && is.number(obj.y2);
},
promise: function promise(obj) {
return is.object(obj) && is.fn(obj.then);
},
touch: function touch() {
return window && ('ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch);
},
gecko: function gecko() {
return window && (typeof InstallTrigger !== 'undefined' || 'MozAppearance' in document.documentElement.style);
},
webkit: function webkit() {
return window && (typeof webkitURL !== 'undefined' || 'WebkitAppearance' in document.documentElement.style);
},
chromium: function chromium() {
return window && typeof chrome !== 'undefined';
},
khtml: function khtml() {
return navigator && navigator.vendor.match(/kde/i); // probably a better way to detect this...
},
khtmlEtc: function khtmlEtc() {
return is.khtml() || is.webkit() || is.chromium();
},
ms: function ms() {
return navigator && navigator.userAgent.match(/msie|trident|edge/i); // probably a better way to detect this...
},
windows: function windows() {
return navigator && navigator.appVersion.match(/Win/i);
},
mac: function mac() {
return navigator && navigator.appVersion.match(/Mac/i);
},
linux: function linux() {
return navigator && navigator.appVersion.match(/Linux/i);
},
unix: function unix() {
return navigator && navigator.appVersion.match(/X11/i);
}
};
module.exports = is;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*global console */
var is = __webpack_require__(0);
var math = __webpack_require__(2);
var util = {
MAX_INT: Number.MAX_SAFE_INTEGER || 9007199254740991,
trueify: function trueify() {
return true;
},
falsify: function falsify() {
return false;
},
zeroify: function zeroify() {
return 0;
},
noop: function noop() {},
error: function error(msg) {
/* eslint-disable */
if (console.error) {
console.error.apply(console, arguments);
if (console.trace) {
console.trace();
}
} else {
console.log.apply(console, arguments);
if (console.trace) {
console.trace();
}
}
/* eslint-enable */
},
clone: function clone(obj) {
return this.extend({}, obj);
},
// gets a shallow copy of the argument
copy: function copy(obj) {
if (obj == null) {
return obj;
}if (is.array(obj)) {
return obj.slice();
} else if (is.plainObject(obj)) {
return this.clone(obj);
} else {
return obj;
}
},
copyArray: function copyArray(arr) {
return arr.slice();
},
clonePosition: function clonePosition(pos) {
return { x: pos.x, y: pos.y };
},
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
? // genetate 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;
}
};
util.makeBoundingBox = math.makeBoundingBox.bind(math);
util._staticEmptyObject = {};
util.staticEmptyObject = function () {
return util._staticEmptyObject;
};
util.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;
};
util.assign = util.extend;
util.default = function (val, def) {
if (val === undefined) {
return def;
} else {
return val;
}
};
util.removeFromArray = function (arr, ele, manyCopies) {
for (var i = arr.length; i >= 0; i--) {
if (arr[i] === ele) {
arr.splice(i, 1);
if (!manyCopies) {
break;
}
}
}
};
util.clearArray = function (arr) {
arr.splice(0, arr.length);
};
util.push = function (arr, otherArr) {
for (var i = 0; i < otherArr.length; i++) {
var el = otherArr[i];
arr.push(el);
}
};
util.getPrefixedProperty = function (obj, propName, prefix) {
if (prefix) {
propName = this.prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth
}
return obj[propName];
};
util.setPrefixedProperty = function (obj, propName, prefix, value) {
if (prefix) {
propName = this.prependCamel(prefix, propName); // e.g. (labelWidth, source) => sourceLabelWidth
}
obj[propName] = value;
};
[__webpack_require__(21), __webpack_require__(22), { memoize: __webpack_require__(13) }, __webpack_require__(23), __webpack_require__(24), __webpack_require__(25), __webpack_require__(27)].forEach(function (req) {
util.extend(util, req);
});
module.exports = util;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = {};
math.arePositionsSame = function (p1, p2) {
return p1.x === p2.x && p1.y === p2.y;
};
math.copyPosition = function (p) {
return { x: p.x, y: p.y };
};
math.modelToRenderedPosition = function (p, zoom, pan) {
return {
x: p.x * zoom + pan.x,
y: p.y * zoom + pan.y
};
};
math.renderedToModelPosition = function (p, zoom, pan) {
return {
x: (p.x - pan.x) / zoom,
y: (p.y - pan.y) / zoom
};
};
math.array2point = function (arr) {
return {
x: arr[0],
y: arr[1]
};
};
math.deg2rad = function (deg) {
return Math.PI * deg / 180;
};
math.getAngleFromDisp = function (dispX, dispY) {
return Math.atan2(dispY, dispX) - Math.PI / 2;
};
math.log2 = Math.log2 || function (n) {
return Math.log(n) / Math.log(2);
};
math.signum = function (x) {
if (x > 0) {
return 1;
} else if (x < 0) {
return -1;
} else {
return 0;
}
};
math.dist = function (p1, p2) {
return Math.sqrt(math.sqdist(p1, p2));
};
math.sqdist = function (p1, p2) {
var dx = p2.x - p1.x;
var dy = p2.y - p1.y;
return dx * dx + dy * dy;
};
// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves
math.qbezierAt = function (p0, p1, p2, t) {
return (1 - t) * (1 - t) * p0 + 2 * (1 - t) * t * p1 + t * t * p2;
};
math.qbezierPtAt = function (p0, p1, p2, t) {
return {
x: math.qbezierAt(p0.x, p1.x, p2.x, t),
y: math.qbezierAt(p0.y, p1.y, p2.y, t)
};
};
math.lineAt = function (p0, p1, t, d) {
var vec = {
x: p1.x - p0.x,
y: p1.y - p0.y
};
var vecDist = math.dist(p0, p1);
var normVec = {
x: vec.x / vecDist,
y: vec.y / vecDist
};
t = t == null ? 0 : t;
d = d != null ? d : t * vecDist;
return {
x: p0.x + normVec.x * d,
y: p0.y + normVec.y * d
};
};
math.lineAtDist = function (p0, p1, d) {
return math.lineAt(p0, p1, undefined, d);
};
// get angle at A via cosine law
math.triangleAngle = function (A, B, C) {
var a = math.dist(B, C);
var b = math.dist(A, C);
var c = math.dist(A, B);
return Math.acos((a * a + b * b - c * c) / (2 * a * b));
};
math.bound = function (min, val, max) {
return Math.max(min, Math.min(max, val));
};
// makes a full bb (x1, y1, x2, y2, w, h) from implicit params
math.makeBoundingBox = function (bb) {
if (bb == null) {
return {
x1: Infinity,
y1: Infinity,
x2: -Infinity,
y2: -Infinity,
w: 0,
h: 0
};
} else if (bb.x1 != null && bb.y1 != null) {
if (bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1) {
return {
x1: bb.x1,
y1: bb.y1,
x2: bb.x2,
y2: bb.y2,
w: bb.x2 - bb.x1,
h: bb.y2 - bb.y1
};
} else if (bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0) {
return {
x1: bb.x1,
y1: bb.y1,
x2: bb.x1 + bb.w,
y2: bb.y1 + bb.h,
w: bb.w,
h: bb.h
};
}
}
};
math.updateBoundingBox = function (bb1, bb2) {
// update bb1 with bb2 bounds
bb1.x1 = Math.min(bb1.x1, bb2.x1);
bb1.x2 = Math.max(bb1.x2, bb2.x2);
bb1.w = bb1.x2 - bb1.x1;
bb1.y1 = Math.min(bb1.y1, bb2.y1);
bb1.y2 = Math.max(bb1.y2, bb2.y2);
bb1.h = bb1.y2 - bb1.y1;
};
math.expandBoundingBoxByPoint = function (bb, x, y) {
bb.x1 = Math.min(bb.x1, x);
bb.x2 = Math.max(bb.x2, x);
bb.w = bb.x2 - bb.x1;
bb.y1 = Math.min(bb.y1, y);
bb.y2 = Math.max(bb.y2, y);
bb.h = bb.y2 - bb.y1;
};
math.expandBoundingBox = function (bb, padding) {
bb.x1 -= padding;
bb.x2 += padding;
bb.y1 -= padding;
bb.y2 += padding;
bb.w = bb.x2 - bb.x1;
bb.h = bb.y2 - bb.y1;
return bb;
};
math.boundingBoxesIntersect = function (bb1, bb2) {
// case: one bb to right of other
if (bb1.x1 > bb2.x2) {
return false;
}
if (bb2.x1 > bb1.x2) {
return false;
}
// case: one bb to left of other
if (bb1.x2 < bb2.x1) {
return false;
}
if (bb2.x2 < bb1.x1) {
return false;
}
// case: one bb above other
if (bb1.y2 < bb2.y1) {
return false;
}
if (bb2.y2 < bb1.y1) {
return false;
}
// case: one bb below other
if (bb1.y1 > bb2.y2) {
return false;
}
if (bb2.y1 > bb1.y2) {
return false;
}
// otherwise, must have some overlap
return true;
};
math.inBoundingBox = function (bb, x, y) {
return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;
};
math.pointInBoundingBox = function (bb, pt) {
return this.inBoundingBox(bb, pt.x, pt.y);
};
math.boundingBoxInBoundingBox = function (bb1, bb2) {
return math.inBoundingBox(bb1, bb2.x1, bb2.y1) && math.inBoundingBox(bb1, bb2.x2, bb2.y2);
};
math.roundRectangleIntersectLine = function (x, y, nodeX, nodeY, width, height, padding) {
var cornerRadius = this.getRoundRectangleRadius(width, height);
var halfWidth = width / 2;
var halfHeight = height / 2;
// Check intersections with straight line segments
var straightLineIntersections = void 0;
// Top segment, left to right
{
var topStartX = nodeX - halfWidth + cornerRadius - padding;
var topStartY = nodeY - halfHeight - padding;
var topEndX = nodeX + halfWidth - cornerRadius + padding;
var topEndY = topStartY;
straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);
if (straightLineIntersections.length > 0) {
return straightLineIntersections;
}
}
// Right segment, top to bottom
{
var rightStartX = nodeX + halfWidth + padding;
var rightStartY = nodeY - halfHeight + cornerRadius - padding;
var rightEndX = rightStartX;
var rightEndY = nodeY + halfHeight - cornerRadius + padding;
straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);
if (straightLineIntersections.length > 0) {
return straightLineIntersections;
}
}
// Bottom segment, left to right
{
var bottomStartX = nodeX - halfWidth + cornerRadius - padding;
var bottomStartY = nodeY + halfHeight + padding;
var bottomEndX = nodeX + halfWidth - cornerRadius + padding;
var bottomEndY = bottomStartY;
straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);
if (straightLineIntersections.length > 0) {
return straightLineIntersections;
}
}
// Left segment, top to bottom
{
var leftStartX = nodeX - halfWidth - padding;
var leftStartY = nodeY - halfHeight + cornerRadius - padding;
var leftEndX = leftStartX;
var leftEndY = nodeY + halfHeight - cornerRadius + padding;
straightLineIntersections = this.finiteLinesIntersect(x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);
if (straightLineIntersections.length > 0) {
return straightLineIntersections;
}
}
// Check intersections with arc segments
var arcIntersections = void 0;
// Top Left
{
var topLeftCenterX = nodeX - halfWidth + cornerRadius;
var topLeftCenterY = nodeY - halfHeight + cornerRadius;
arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, topLeftCenterX, topLeftCenterY, cornerRadius + padding);
// Ensure the intersection is on the desired quarter of the circle
if (arcIntersections.length > 0 && arcIntersections[0] <= topLeftCenterX && arcIntersections[1] <= topLeftCenterY) {
return [arcIntersections[0], arcIntersections[1]];
}
}
// Top Right
{
var topRightCenterX = nodeX + halfWidth - cornerRadius;
var topRightCenterY = nodeY - halfHeight + cornerRadius;
arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, topRightCenterX, topRightCenterY, cornerRadius + padding);
// Ensure the intersection is on the desired quarter of the circle
if (arcIntersections.length > 0 && arcIntersections[0] >= topRightCenterX && arcIntersections[1] <= topRightCenterY) {
return [arcIntersections[0], arcIntersections[1]];
}
}
// Bottom Right
{
var bottomRightCenterX = nodeX + halfWidth - cornerRadius;
var bottomRightCenterY = nodeY + halfHeight - cornerRadius;
arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, bottomRightCenterX, bottomRightCenterY, cornerRadius + padding);
// Ensure the intersection is on the desired quarter of the circle
if (arcIntersections.length > 0 && arcIntersections[0] >= bottomRightCenterX && arcIntersections[1] >= bottomRightCenterY) {
return [arcIntersections[0], arcIntersections[1]];
}
}
// Bottom Left
{
var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;
var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;
arcIntersections = this.intersectLineCircle(x, y, nodeX, nodeY, bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding);
// Ensure the intersection is on the desired quarter of the circle
if (arcIntersections.length > 0 && arcIntersections[0] <= bottomLeftCenterX && arcIntersections[1] >= bottomLeftCenterY) {
return [arcIntersections[0], arcIntersections[1]];
}
}
return []; // if nothing
};
math.inLineVicinity = function (x, y, lx1, ly1, lx2, ly2, tolerance) {
var t = tolerance;
var x1 = Math.min(lx1, lx2);
var x2 = Math.max(lx1, lx2);
var y1 = Math.min(ly1, ly2);
var y2 = Math.max(ly1, ly2);
return x1 - t <= x && x <= x2 + t && y1 - t <= y && y <= y2 + t;
};
math.inBezierVicinity = function (x, y, x1, y1, x2, y2, x3, y3, tolerance) {
var bb = {
x1: Math.min(x1, x3, x2) - tolerance,
x2: Math.max(x1, x3, x2) + tolerance,
y1: Math.min(y1, y3, y2) - tolerance,
y2: Math.max(y1, y3, y2) + tolerance
};
// if outside the rough bounding box for the bezier, then it can't be a hit
if (x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2) {
// console.log('bezier out of rough bb')
return false;
} else {
// console.log('do more expensive check');
return true;
}
};
math.solveQuadratic = function (a, b, c, val) {
c -= val;
var r = b * b - 4 * a * c;
if (r < 0) {
return [];
}
var sqrtR = Math.sqrt(r);
var denom = 2 * a;
var root1 = (-b + sqrtR) / denom;
var root2 = (-b - sqrtR) / denom;
return [root1, root2];
};
math.solveCubic = function (a, b, c, d, result) {
// Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where
// r is the real component, i is the imaginary component
// An implementation of the Cardano method from the year 1545
// http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots
b /= a;
c /= a;
d /= a;
var discriminant = void 0,
q = void 0,
r = void 0,
dum1 = void 0,
s = void 0,
t = void 0,
term1 = void 0,
r13 = void 0;
q = (3.0 * c - b * b) / 9.0;
r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));
r /= 54.0;
discriminant = q * q * q + r * r;
result[1] = 0;
term1 = b / 3.0;
if (discriminant > 0) {
s = r + Math.sqrt(discriminant);
s = s < 0 ? -Math.pow(-s, 1.0 / 3.0) : Math.pow(s, 1.0 / 3.0);
t = r - Math.sqrt(discriminant);
t = t < 0 ? -Math.pow(-t, 1.0 / 3.0) : Math.pow(t, 1.0 / 3.0);
result[0] = -term1 + s + t;
term1 += (s + t) / 2.0;
result[4] = result[2] = -term1;
term1 = Math.sqrt(3.0) * (-t + s) / 2;
result[3] = term1;
result[5] = -term1;
return;
}
result[5] = result[3] = 0;
if (discriminant === 0) {
r13 = r < 0 ? -Math.pow(-r, 1.0 / 3.0) : Math.pow(r, 1.0 / 3.0);
result[0] = -term1 + 2.0 * r13;
result[4] = result[2] = -(r13 + term1);
return;
}
q = -q;
dum1 = q * q * q;
dum1 = Math.acos(r / Math.sqrt(dum1));
r13 = 2.0 * Math.sqrt(q);
result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);
result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);
result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);
return;
};
math.sqdistToQuadraticBezier = function (x, y, x1, y1, x2, y2, x3, y3) {
// Find minimum distance by using the minimum of the distance
// function between the given point and the curve
// This gives the coefficients of the resulting cubic equation
// whose roots tell us where a possible minimum is
// (Coefficients are divided by 4)
var a = 1.0 * x1 * x1 - 4 * x1 * x2 + 2 * x1 * x3 + 4 * x2 * x2 - 4 * x2 * x3 + x3 * x3 + y1 * y1 - 4 * y1 * y2 + 2 * y1 * y3 + 4 * y2 * y2 - 4 * y2 * y3 + y3 * y3;
var b = 1.0 * 9 * x1 * x2 - 3 * x1 * x1 - 3 * x1 * x3 - 6 * x2 * x2 + 3 * x2 * x3 + 9 * y1 * y2 - 3 * y1 * y1 - 3 * y1 * y3 - 6 * y2 * y2 + 3 * y2 * y3;
var c = 1.0 * 3 * x1 * x1 - 6 * x1 * x2 + x1 * x3 - x1 * x + 2 * x2 * x2 + 2 * x2 * x - x3 * x + 3 * y1 * y1 - 6 * y1 * y2 + y1 * y3 - y1 * y + 2 * y2 * y2 + 2 * y2 * y - y3 * y;
var d = 1.0 * x1 * x2 - x1 * x1 + x1 * x - x2 * x + y1 * y2 - y1 * y1 + y1 * y - y2 * y;
// debug("coefficients: " + a / a + ", " + b / a + ", " + c / a + ", " + d / a);
var roots = [];
// Use the cubic solving algorithm
this.solveCubic(a, b, c, d, roots);
var zeroThreshold = 0.0000001;
var params = [];
for (var index = 0; index < 6; index += 2) {
if (Math.abs(roots[index + 1]) < zeroThreshold && roots[index] >= 0 && roots[index] <= 1.0) {
params.push(roots[index]);
}
}
params.push(1.0);
params.push(0.0);
var minDistanceSquared = -1;
var curX = void 0,
curY = void 0,
distSquared = void 0;
for (var i = 0; i < params.length; i++) {
curX = Math.pow(1.0 - params[i], 2.0) * x1 + 2.0 * (1 - params[i]) * params[i] * x2 + params[i] * params[i] * x3;
curY = Math.pow(1 - params[i], 2.0) * y1 + 2 * (1.0 - params[i]) * params[i] * y2 + params[i] * params[i] * y3;
distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2);
// debug('distance for param ' + params[i] + ": " + Math.sqrt(distSquared));
if (minDistanceSquared >= 0) {
if (distSquared < minDistanceSquared) {
minDistanceSquared = distSquared;
}
} else {
minDistanceSquared = distSquared;
}
}
return minDistanceSquared;
};
math.sqdistToFiniteLine = function (x, y, x1, y1, x2, y2) {
var offset = [x - x1, y - y1];
var line = [x2 - x1, y2 - y1];
var lineSq = line[0] * line[0] + line[1] * line[1];
var hypSq = offset[0] * offset[0] + offset[1] * offset[1];
var dotProduct = offset[0] * line[0] + offset[1] * line[1];
var adjSq = dotProduct * dotProduct / lineSq;
if (dotProduct < 0) {
return hypSq;
}
if (adjSq > lineSq) {
return (x - x2) * (x - x2) + (y - y2) * (y - y2);
}
return hypSq - adjSq;
};
math.pointInsidePolygonPoints = function (x, y, points) {
var x1 = void 0,
y1 = void 0,
x2 = void 0,
y2 = void 0;
var y3 = void 0;
// Intersect with vertical line through (x, y)
var up = 0;
// let down = 0;
for (var i = 0; i < points.length / 2; i++) {
x1 = points[i * 2];
y1 = points[i * 2 + 1];
if (i + 1 < points.length / 2) {
x2 = points[(i + 1) * 2];
y2 = points[(i + 1) * 2 + 1];
} else {
x2 = points[(i + 1 - points.length / 2) * 2];
y2 = points[(i + 1 - points.length / 2) * 2 + 1];
}
if (x1 == x && x2 == x) {
// then ignore
} else if (x1 >= x && x >= x2 || x1 <= x && x <= x2) {
y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;
if (y3 > y) {
up++;
}
// if( y3 < y ){
// down++;
// }
} else {
continue;
}
}
if (up % 2 === 0) {
return false;
} else {
return true;
}
};
math.pointInsidePolygon = function (x, y, basePoints, centerX, centerY, width, height, direction, padding) {
//let direction = arguments[6];
var transformedPoints = new Array(basePoints.length);
// Gives negative angle
var angle = void 0;
if (direction[0] != null) {
angle = Math.atan(direction[1] / direction[0]);
if (direction[0] < 0) {
angle = angle + Math.PI / 2;
} else {
angle = -angle - Math.PI / 2;
}
} else {
angle = direction;
}
var cos = Math.cos(-angle);
var sin = Math.sin(-angle);
// console.log("base: " + basePoints);
for (var i = 0; i < transformedPoints.length / 2; i++) {
transformedPoints[i * 2] = width / 2 * (basePoints[i * 2] * cos - basePoints[i * 2 + 1] * sin);
transformedPoints[i * 2 + 1] = height / 2 * (basePoints[i * 2 + 1] * cos + basePoints[i * 2] * sin);
transformedPoints[i * 2] += centerX;
transformedPoints[i * 2 + 1] += centerY;
}
var points = void 0;
if (padding > 0) {
var expandedLineSet = this.expandPolygon(transformedPoints, -padding);
points = this.joinLines(expandedLineSet);
} else {
points = transformedPoints;
}
return math.pointInsidePolygonPoints(x, y, points);
};
math.joinLines = function (lineSet) {
var vertices = new Array(lineSet.length / 2);
var currentLineStartX = void 0,
currentLineStartY = void 0,
currentLineEndX = void 0,
currentLineEndY = void 0;
var nextLineStartX = void 0,
nextLineStartY = void 0,
nextLineEndX = void 0,
nextLineEndY = void 0;
for (var i = 0; i < lineSet.length / 4; i++) {
currentLineStartX = lineSet[i * 4];
currentLineStartY = lineSet[i * 4 + 1];
currentLineEndX = lineSet[i * 4 + 2];
currentLineEndY = lineSet[i * 4 + 3];
if (i < lineSet.length / 4 - 1) {
nextLineStartX = lineSet[(i + 1) * 4];
nextLineStartY = lineSet[(i + 1) * 4 + 1];
nextLineEndX = lineSet[(i + 1) * 4 + 2];
nextLineEndY = lineSet[(i + 1) * 4 + 3];
} else {
nextLineStartX = lineSet[0];
nextLineStartY = lineSet[1];
nextLineEndX = lineSet[2];
nextLineEndY = lineSet[3];
}
var intersection = this.finiteLinesIntersect(currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY, nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY, true);
vertices[i * 2] = intersection[0];
vertices[i * 2 + 1] = intersection[1];
}
return vertices;
};
math.expandPolygon = function (points, pad) {
var expandedLineSet = new Array(points.length * 2);
var currentPointX = void 0,
currentPointY = void 0,
nextPointX = void 0,
nextPointY = void 0;
for (var i = 0; i < points.length / 2; i++) {
currentPointX = points[i * 2];
currentPointY = points[i * 2 + 1];
if (i < points.length / 2 - 1) {
nextPointX = points[(i + 1) * 2];
nextPointY = points[(i + 1) * 2 + 1];
} else {
nextPointX = points[0];
nextPointY = points[1];
}
// Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]
// Assume CCW polygon winding
var offsetX = nextPointY - currentPointY;
var offsetY = -(nextPointX - currentPointX);
// Normalize
var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
var normalizedOffsetX = offsetX / offsetLength;
var normalizedOffsetY = offsetY / offsetLength;
expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;
expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;
expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;
expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;
}
return expandedLineSet;
};
math.intersectLineEllipse = function (x, y, centerX, centerY, ellipseWradius, ellipseHradius) {
var dispX = centerX - x;
var dispY = centerY - y;
dispX /= ellipseWradius;
dispY /= ellipseHradius;
var len = Math.sqrt(dispX * dispX + dispY * dispY);
var newLength = len - 1;
if (newLength < 0) {
return [];
}
var lenProportion = newLength / len;
return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];
};
math.checkInEllipse = function (x, y, width, height, centerX, centerY, padding) {
x -= centerX;
y -= centerY;
x /= width / 2 + padding;
y /= height / 2 + padding;
return x * x + y * y <= 1;
};
// Returns intersections of increasing distance from line's start point
math.intersectLineCircle = function (x1, y1, x2, y2, centerX, centerY, radius) {
// Calculate d, direction vector of line
var d = [x2 - x1, y2 - y1]; // Direction vector of line
var f = [x1 - centerX, y1 - centerY];
var a = d[0] * d[0] + d[1] * d[1];
var b = 2 * (f[0] * d[0] + f[1] * d[1]);
var c = f[0] * f[0] + f[1] * f[1] - radius * radius;
var discriminant = b * b - 4 * a * c;
if (discriminant < 0) {
return [];
}
var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);
var tMin = Math.min(t1, t2);
var tMax = Math.max(t1, t2);
var inRangeParams = [];
if (tMin >= 0 && tMin <= 1) {
inRangeParams.push(tMin);
}
if (tMax >= 0 && tMax <= 1) {
inRangeParams.push(tMax);
}
if (inRangeParams.length === 0) {
return [];
}
var nearIntersectionX = inRangeParams[0] * d[0] + x1;
var nearIntersectionY = inRangeParams[0] * d[1] + y1;
if (inRangeParams.length > 1) {
if (inRangeParams[0] == inRangeParams[1]) {
return [nearIntersectionX, nearIntersectionY];
} else {
var farIntersectionX = inRangeParams[1] * d[0] + x1;
var farIntersectionY = inRangeParams[1] * d[1] + y1;
return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];
}
} else {
return [nearIntersectionX, nearIntersectionY];
}
};
math.findCircleNearPoint = function (centerX, centerY, radius, farX, farY) {
var displacementX = farX - centerX;
var displacementY = farY - centerY;
var distance = Math.sqrt(displacementX * displacementX + displacementY * displacementY);
var unitDisplacementX = displacementX / distance;
var unitDisplacementY = displacementY / distance;
return [centerX + unitDisplacementX * radius, centerY + unitDisplacementY * radius];
};
math.findMaxSqDistanceToOrigin = function (points) {
var maxSqDistance = 0.000001;
var sqDistance = void 0;
for (var i = 0; i < points.length / 2; i++) {
sqDistance = points[i * 2] * points[i * 2] + points[i * 2 + 1] * points[i * 2 + 1];
if (sqDistance > maxSqDistance) {
maxSqDistance = sqDistance;
}
}
return maxSqDistance;
};
math.midOfThree = function (a, b, c) {
if (b <= a && a <= c || c <= a && a <= b) {
return a;
} else if (a <= b && b <= c || c <= b && b <= a) {
return b;
} else {
return c;
}
};
// (x1,y1)=>(x2,y2) intersect with (x3,y3)=>(x4,y4)
math.finiteLinesIntersect = function (x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {
var dx13 = x1 - x3;
var dx21 = x2 - x1;
var dx43 = x4 - x3;
var dy13 = y1 - y3;
var dy21 = y2 - y1;
var dy43 = y4 - y3;
var ua_t = dx43 * dy13 - dy43 * dx13;
var ub_t = dx21 * dy13 - dy21 * dx13;
var u_b = dy43 * dx21 - dx43 * dy21;
if (u_b !== 0) {
var ua = ua_t / u_b;
var ub = ub_t / u_b;
var flptThreshold = 0.001;
var min = 0 - flptThreshold;
var max = 1 + flptThreshold;
if (min <= ua && ua <= max && min <= ub && ub <= max) {
return [x1 + ua * dx21, y1 + ua * dy21];
} else {
if (!infiniteLines) {
return [];
} else {
return [x1 + ua * dx21, y1 + ua * dy21];
}
}
} else {
if (ua_t === 0 || ub_t === 0) {
// Parallel, coincident lines. Check if overlap
// Check endpoint of second line
if (this.midOfThree(x1, x2, x4) === x4) {
return [x4, y4];
}
// Check start point of second line
if (this.midOfThree(x1, x2, x3) === x3) {
return [x3, y3];
}
// Endpoint of first line
if (this.midOfThree(x3, x4, x2) === x2) {
return [x2, y2];
}
return [];
} else {
// Parallel, non-coincident
return [];
}
}
};
// math.polygonIntersectLine( x, y, basePoints, centerX, centerY, width, height, padding )
// intersect a node polygon (pts transformed)
//
// math.polygonIntersectLine( x, y, basePoints, centerX, centerY )
// intersect the points (no transform)
math.polygonIntersectLine = function (x, y, basePoints, centerX, centerY, width, height, padding) {
var intersections = [];
var intersection = void 0;
var transformedPoints = new Array(basePoints.length);
var doTransform = true;
if (arguments.length === 5) {
doTransform = false;
}
var points = void 0;
if (doTransform) {
for (var i = 0; i < transformedPoints.length / 2; i++) {
transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;
transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;
}
if (padding > 0) {
var expandedLineSet = math.expandPolygon(transformedPoints, -padding);
points = math.joinLines(expandedLineSet);
} else {
points = transformedPoints;
}
} else {
points = basePoints;
}
var currentX = void 0,
currentY = void 0,
nextX = void 0,
nextY = void 0;
for (var _i = 0; _i < points.length / 2; _i++) {
currentX = points[_i * 2];
currentY = points[_i * 2 + 1];
if (_i < points.length / 2 - 1) {
nextX = points[(_i + 1) * 2];
nextY = points[(_i + 1) * 2 + 1];
} else {
nextX = points[0];
nextY = points[1];
}
intersection = this.finiteLinesIntersect(x, y, centerX, centerY, currentX, currentY, nextX, nextY);
if (intersection.length !== 0) {
intersections.push(intersection[0], intersection[1]);
}
}
return intersections;
};
math.shortenIntersection = function (intersection, offset, amount) {
var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];
var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);
var lenRatio = (length - amount) / length;
if (lenRatio < 0) {
lenRatio = 0.00001;
}
return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];
};
math.generateUnitNgonPointsFitToSquare = function (sides, rotationRadians) {
var points = math.generateUnitNgonPoints(sides, rotationRadians);
points = math.fitPolygonToSquare(points);
return points;
};
math.fitPolygonToSquare = function (points) {
var x = void 0,
y = void 0;
var sides = points.length / 2;
var minX = Infinity,
minY = Infinity,
maxX = -Infinity,
maxY = -Infinity;
for (var i = 0; i < sides; i++) {
x = points[2 * i];
y = points[2 * i + 1];
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
// stretch factors
var sx = 2 / (maxX - minX);
var sy = 2 / (maxY - minY);
for (var _i2 = 0; _i2 < sides; _i2++) {
x = points[2 * _i2] = points[2 * _i2] * sx;
y = points[2 * _i2 + 1] = points[2 * _i2 + 1] * sy;
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
if (minY < -1) {
for (var _i3 = 0; _i3 < sides; _i3++) {
y = points[2 * _i3 + 1] = points[2 * _i3 + 1] + (-1 - minY);
}
}
return points;
};
math.generateUnitNgonPoints = function (sides, rotationRadians) {
var increment = 1.0 / sides * 2 * Math.PI;
var startAngle = sides % 2 === 0 ? Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;
startAngle += rotationRadians;
var points = new Array(sides * 2);
var currentAngle = void 0;
for (var i = 0; i < sides; i++) {
currentAngle = i * increment + startAngle;
points[2 * i] = Math.cos(currentAngle); // x
points[2 * i + 1] = Math.sin(-currentAngle); // y
}
return points;
};
math.getRoundRectangleRadius = function (width, height) {
// Set the default radius, unless half of width or height is smaller than default
return Math.min(width / 4, height / 4, 8);
};
math.getCutRectangleCornerLength = function () {
return 8;
};
math.bezierPtsToQuadCoeff = function (p0, p1, p2) {
return [p0 - 2 * p1 + p2, 2 * (p1 - p0), p0];
};
math.getBarrelCurveConstants = function (width, height) {
// get curve width, height, and control point position offsets as a percentage of node height / width
return {
heightOffset: Math.min(15, 0.05 * height),
widthOffset: Math.min(100, 0.25 * width),
ctrlPtOffsetPct: 0.05
};
};
module.exports = math;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = typeof window === 'undefined' ? null : window; // eslint-disable-line no-undef
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// use this module to cherry pick functions into your prototype
// (useful for functions shared between the core and collections, for example)
// e.g.
// let foo = define.foo({ /* params... */ })
var util = __webpack_require__(1);
var define = {};
[__webpack_require__(44), __webpack_require__(46), __webpack_require__(47)].forEach(function (m) {
util.assign(define, m);
});
module.exports = define;
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/*!
Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable
Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com)
Licensed under The MIT License (http://opensource.org/licenses/MIT)
*/
/* promise states [Promises/A+ 2.1] */
var STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */
var STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */
var STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */
/* promise object constructor */
var api = function api(executor) {
/* optionally support non-constructor/plain-function call */
if (!(this instanceof api)) return new api(executor);
/* initialize object */
this.id = 'Thenable/1.0.7';
this.state = STATE_PENDING; /* initial state */
this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */
this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */
this.onFulfilled = []; /* initial handlers */
this.onRejected = []; /* initial handlers */
/* provide optional information-hiding proxy */
this.proxy = {
then: this.then.bind(this)
};
/* support optional executor function */
if (typeof executor === 'function') executor.call(this, this.fulfill.bind(this), this.reject.bind(this));
};
/* promise API methods */
api.prototype = {
/* promise resolving methods */
fulfill: function fulfill(value) {
return deliver(this, STATE_FULFILLED, 'fulfillValue', value);
},
reject: function reject(value) {
return deliver(this, STATE_REJECTED, 'rejectReason', value);
},
/* "The then Method" [Promises/A+ 1.1, 1.2, 2.2] */
then: function then(onFulfilled, onRejected) {
var curr = this;
var next = new api(); /* [Promises/A+ 2.2.7] */
curr.onFulfilled.push(resolver(onFulfilled, next, 'fulfill')); /* [Promises/A+ 2.2.2/2.2.6] */
curr.onRejected.push(resolver(onRejected, next, 'reject')); /* [Promises/A+ 2.2.3/2.2.6] */
execute(curr);
return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */
}
};
/* deliver an action */
var deliver = function deliver(curr, state, name, value) {
if (curr.state === STATE_PENDING) {
curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */
curr[name] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */
execute(curr);
}
return curr;
};
/* execute all handlers */
var execute = function execute(curr) {
if (curr.state === STATE_FULFILLED) execute_handlers(curr, 'onFulfilled', curr.fulfillValue);else if (curr.state === STATE_REJECTED) execute_handlers(curr, 'onRejected', curr.rejectReason);
};
/* execute particular set of handlers */
var execute_handlers = function execute_handlers(curr, name, value) {
/* global setImmediate: true */
/* global setTimeout: true */
/* short-circuit processing */
if (curr[name].length === 0) return;
/* iterate over all handlers, exactly once */
var handlers = curr[name];
curr[name] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */
var func = function func() {
for (var i = 0; i < handlers.length; i++) {
handlers[i](value);
} /* [Promises/A+ 2.2.5] */
};
/* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */
if (typeof setImmediate === 'function') setImmediate(func);else setTimeout(func, 0);
};
/* generate a resolver function */
var resolver = function resolver(cb, next, method) {
return function (value) {
if (typeof cb !== 'function') /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */
next[method].call(next, value); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */
else {
var result;
try {
result = cb(value);
} /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */
catch (e) {
next.reject(e); /* [Promises/A+ 2.2.7.2] */
return;
}
resolve(next, result); /* [Promises/A+ 2.2.7.1] */
}
};
};
/* "Promise Resolution Procedure" */ /* [Promises/A+ 2.3] */
var resolve = function resolve(promise, x) {
/* sanity check arguments */ /* [Promises/A+ 2.3.1] */
if (promise === x || promise.proxy === x) {
promise.reject(new TypeError('cannot resolve promise with itself'));
return;
}
/* surgically check for a "then" method
(mainly to just call the "getter" of "then" only once) */
var then;
if ((typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function') {
try {
then = x.then;
} /* [Promises/A+ 2.3.3.1, 3.5] */
catch (e) {
promise.reject(e); /* [Promises/A+ 2.3.3.2] */
return;
}
}
/* handle own Thenables [Promises/A+ 2.3.2]
and similar "thenables" [Promises/A+ 2.3.3] */
if (typeof then === 'function') {
var resolved = false;
try {
/* call retrieved "then" method */ /* [Promises/A+ 2.3.3.3] */
then.call(x,
/* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */
function (y) {
if (resolved) return;resolved = true; /* [Promises/A+ 2.3.3.3.3] */
if (y === x) /* [Promises/A+ 3.6] */
promise.reject(new TypeError('circular thenable chain'));else resolve(promise, y);
},
/* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */
function (r) {
if (resolved) return;resolved = true; /* [Promises/A+ 2.3.3.3.3] */
promise.reject(r);
});
} catch (e) {
if (!resolved) /* [Promises/A+ 2.3.3.3.3] */
promise.reject(e); /* [Promises/A+ 2.3.3.3.4] */
}
return;
}
/* handle other values */
promise.fulfill(x); /* [Promises/A+ 2.3.4, 2.3.3.4] */
};
// so we always have Promise.all()
api.all = function (ps) {
return new api(function (resolveAll, rejectAll) {
var vals = new Array(ps.length);
var doneCount = 0;
var fulfill = function fulfill(i, val) {
vals[i] = val;
doneCount++;
if (doneCount === ps.length) {
resolveAll(vals);
}
};
for (var i = 0; i < ps.length; i++) {
(function (i) {
var p = ps[i];
var isPromise = p != null && p.then != null;
if (isPromise) {
p.then(function (val) {
fulfill(i, val);
}, function (err) {
rejectAll(err);
});
} else {
var val = p;
fulfill(i, val);
}
})(i);
}
});
};
api.resolve = function (val) {
return new api(function (resolve, reject) {
resolve(val);
});
};
api.reject = function (val) {
return new api(function (resolve, reject) {
reject(val);
});
};
module.exports = typeof Promise !== 'undefined' ? Promise : api; // eslint-disable-line no-undef
/***/ }),
/* 6 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var newQuery = __webpack_require__(10);
var Selector = function Selector(selector) {
var self = this;
self._private = {
selectorText: selector,
invalid: true
};
if (selector == null || is.string(selector) && selector.match(/^\s*$/)) {
self.length = 0;
} else if (selector === '*' || selector === 'edge' || selector === 'node') {
// make single, group-only selectors cheap to make and cheap to filter
self[0] = newQuery();
self[0].group = selector === '*' ? selector : selector + 's';
self[0].groupOnly = true;
self[0].length = 1;
self._private.invalid = false;
self.length = 1;
} else if (is.elementOrCollection(selector)) {
var collection = selector.collection();
self[0] = newQuery();
self[0].collection = collection;
self[0].length = 1;
self.length = 1;
} else if (is.fn(selector)) {
self[0] = newQuery();
self[0].filter = selector;
self[0].length = 1;
self.length = 1;
} else if (is.string(selector)) {
if (!self.parse(selector)) {
return;
}
} else {
util.error('A selector must be created from a string; found ', selector);
return;
}
self._private.invalid = false;
};
var selfn = Selector.prototype;
selfn.valid = function () {
return !this._private.invalid;
};
selfn.invalid = function () {
return this._private.invalid;
};
selfn.text = function () {
return this._private.selectorText;
};
selfn.size = function () {
return this.length;
};
selfn.eq = function (i) {
return this[i];
};
selfn.sameText = function (otherSel) {
return this.text() === otherSel.text();
};
selfn.toString = selfn.selector = function () {
if (this._private.toStringCache != null) {
return this._private.toStringCache;
}
var i = void 0;
var str = '';
var clean = function clean(obj) {
if (obj == null) {
return '';
} else {
return obj;
}
};
var cleanVal = function cleanVal(val) {
if (is.string(val)) {
return '"' + val + '"';
} else {
return clean(val);
}
};
var space = function space(val) {
return ' ' + val + ' ';
};
var queryToString = function queryToString(query) {
var str = '';
var j = void 0,
sel = void 0;
if (query.subject === query) {
str += '$';
}
var group = clean(query.group);
str += group.substring(0, group.length - 1);
for (j = 0; j < query.data.length; j++) {
var data = query.data[j];
if (data.value) {
str += '[' + data.field + space(clean(data.operator)) + cleanVal(data.value) + ']';
} else {
str += '[' + clean(data.operator) + data.field + ']';
}
}
for (j = 0; j < query.meta.length; j++) {
var meta = query.meta[j];
str += '[[' + meta.field + space(clean(meta.operator)) + cleanVal(meta.value) + ']]';
}
for (j = 0; j < query.colonSelectors.length; j++) {
sel = query.colonSelectors[i];
str += sel;
}
for (j = 0; j < query.ids.length; j++) {
sel = '#' + query.ids[i];
str += sel;
}
for (j = 0; j < query.classes.length; j++) {
sel = '.' + query.classes[j];
str += sel;
}
if (query.source != null && query.target != null) {
str = queryToString(query.source) + ' -> ' + queryToString(query.target);
}
if (query.connectedNodes != null) {
var n = query.connectedNodes;
str = queryToString(n[0]) + ' <-> ' + queryToString(n[1]);
}
if (query.parent != null) {
str = queryToString(query.parent) + ' > ' + str;
}
if (query.ancestor != null) {
str = queryToString(query.ancestor) + ' ' + str;
}
if (query.child != null) {
str += ' > ' + queryToString(query.child);
}
if (query.descendant != null) {
str += ' ' + queryToString(query.descendant);
}
return str;
};
for (i = 0; i < this.length; i++) {
var query = this[i];
str += queryToString(query);
if (this.length > 1 && i < this.length - 1) {
str += ', ';
}
}
this._private.toStringCache = str;
return str;
};
[__webpack_require__(50), __webpack_require__(53)].forEach(function (p) {
return util.assign(selfn, p);
});
module.exports = Selector;
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var Map = __webpack_require__(28);
var Set = __webpack_require__(8);
var Element = __webpack_require__(14);
// factory for generating edge ids when no id is specified for a new element
var idFactory = {
generate: function generate(cy, element, tryThisId) {
var id = tryThisId != null ? tryThisId : util.uuid();
while (cy.hasElementWithId(id)) {
id = util.uuid();
}
return id;
}
};
// represents a set of nodes, edges, or both together
var Collection = function Collection(cy, elements, options) {
if (cy === undefined || !is.core(cy)) {
util.error('A collection must have a reference to the core');
return;
}
var map = new Map();
var createdElements = false;
if (!elements) {
elements = [];
} else if (elements.length > 0 && is.plainObject(elements[0]) && !is.element(elements[0])) {
createdElements = true;
// make elements from json and restore all at once later
var eles = [];
var elesIds = new Set();
for (var i = 0, l = elements.length; i < l; i++) {
var json = elements[i];
if (json.data == null) {
json.data = {};
}
var data = json.data;
// make sure newly created elements have valid ids
if (data.id == null) {
data.id = idFactory.generate(cy, json);
} else if (cy.hasElementWithId(data.id) || elesIds.has(data.id)) {
continue; // can't create element if prior id already exists
}
var ele = new Element(cy, json, false);
eles.push(ele);
elesIds.add(data.id);
}
elements = eles;
}
this.length = 0;
for (var _i = 0, _l = elements.length; _i < _l; _i++) {
var element = elements[_i];
if (element == null) {
continue;
}
var id = element._private.data.id;
if (options == null || options.unique && !map.has(id)) {
map.set(id, {
index: this.length,
ele: element
});
this[this.length] = element;
this.length++;
}
}
this._private = {
cy: cy,
map: map
};
// restore the elements if we created them from json
if (createdElements) {
this.restore();
}
};
// Functions
////////////////////////////////////////////////////////////////////////////////////////////////////
// keep the prototypes in sync (an element has the same functions as a collection)
// and use elefn and elesfn as shorthands to the prototypes
var elesfn = Element.prototype = Collection.prototype;
elesfn.instanceString = function () {
return 'collection';
};
elesfn.spawn = function (cy, eles, opts) {
if (!is.core(cy)) {
// cy is optional
opts = eles;
eles = cy;
cy = this.cy();
}
return new Collection(cy, eles, opts);
};
elesfn.spawnSelf = function () {
return this.spawn(this);
};
elesfn.cy = function () {
return this._private.cy;
};
elesfn.renderer = function () {
return this._private.cy.renderer();
};
elesfn.element = function () {
return this[0];
};
elesfn.collection = function () {
if (is.collection(this)) {
return this;
} else {
// an element
return new Collection(this._private.cy, [this]);
}
};
elesfn.unique = function () {
return new Collection(this._private.cy, this, { unique: true });
};
elesfn.hasElementWithId = function (id) {
return this._private.map.has(id);
};
elesfn.getElementById = function (id) {
var cy = this._private.cy;
var entry = this._private.map.get(id);
return entry ? entry.ele : new Collection(cy); // get ele or empty collection
};
elesfn.$id = elesfn.getElementById;
elesfn.poolIndex = function () {
var cy = this._private.cy;
var eles = cy._private.elements;
var id = this._private.data.id;
return eles._private.map.get(id).index;
};
elesfn.json = function (obj) {
var ele = this.element();
var cy = this.cy();
if (ele == null && obj) {
return this;
} // can't set to no eles
if (ele == null) {
return undefined;
} // can't get from no eles
var p = ele._private;
if (is.plainObject(obj)) {
// set
cy.startBatch();
if (obj.data) {
ele.data(obj.data);
var data = p.data;
if (ele.isEdge()) {
// source and target are immutable via data()
var move = false;
var spec = {};
var src = obj.data.source;
var tgt = obj.data.target;
if (src != null && src !== data.source) {
spec.source = src;
move = true;
}
if (tgt != null && tgt !== data.target) {
spec.target = tgt;
move = true;
}
if (move) {
ele = ele.move(spec);
}
} else {
// parent is immutable via data()
var parent = obj.data.parent;
if (parent != null && parent !== data.parent) {
ele = ele.move({ parent: parent });
}
}
}
if (obj.position) {
ele.position(obj.position);
}
// ignore group -- immutable
var checkSwitch = function checkSwitch(k, trueFnName, falseFnName) {
var obj_k = obj[k];
if (obj_k != null && obj_k !== p[k]) {
if (obj_k) {
ele[trueFnName]();
} else {
ele[falseFnName]();
}
}
};
checkSwitch('removed', 'remove', 'restore');
checkSwitch('selected', 'select', 'unselect');
checkSwitch('selectable', 'selectify', 'unselectify');
checkSwitch('locked', 'lock', 'unlock');
checkSwitch('grabbable', 'grabify', 'ungrabify');
if (obj.classes != null) {
ele.classes(obj.classes);
}
cy.endBatch();
return this;
} else if (obj === undefined) {
// get
var json = {
data: util.copy(p.data),
position: util.copy(p.position),
group: p.group,
removed: p.removed,
selected: p.selected,
selectable: p.selectable,
locked: p.locked,
grabbable: p.grabbable,
classes: null
};
json.classes = '';
var i = 0;
p.classes.forEach(function (cls) {
return json.classes += i++ === 0 ? cls : ' ' + cls;
});
return json;
}
};
elesfn.jsons = function () {
var jsons = [];
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var json = ele.json();
jsons.push(json);
}
return jsons;
};
elesfn.clone = function () {
var cy = this.cy();
var elesArr = [];
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var json = ele.json();
var clone = new Element(cy, json, false); // NB no restore
elesArr.push(clone);
}
return new Collection(cy, elesArr);
};
elesfn.copy = elesfn.clone;
elesfn.restore = function (notifyRenderer) {
var self = this;
var cy = self.cy();
var cy_p = cy._private;
if (notifyRenderer === undefined) {
notifyRenderer = true;
}
// create arrays of nodes and edges, since we need to
// restore the nodes first
var nodes = [];
var edges = [];
var elements = void 0;
for (var _i2 = 0, l = self.length; _i2 < l; _i2++) {
var ele = self[_i2];
if (!ele.removed()) {
// don't need to handle this ele
continue;
}
// keep nodes first in the array and edges after
if (ele.isNode()) {
// put to front of array if node
nodes.push(ele);
} else {
// put to end of array if edge
edges.push(ele);
}
}
elements = nodes.concat(edges);
var i = void 0;
var removeFromElements = function removeFromElements() {
elements.splice(i, 1);
i--;
};
// now, restore each element
for (i = 0; i < elements.length; i++) {
var _ele = elements[i];
var _private = _ele._private;
var data = _private.data;
// the traversal cache should start fresh when ele is added
_ele.clearTraversalCache();
// set id and validate
if (data.id === undefined) {
data.id = idFactory.generate(cy, _ele);
} else if (is.number(data.id)) {
data.id = '' + data.id; // now it's a string
} else if (is.emptyString(data.id) || !is.string(data.id)) {
util.error('Can not create element with invalid string ID `' + data.id + '`');
// can't create element if it has empty string as id or non-string id
removeFromElements();
continue;
} else if (cy.hasElementWithId(data.id)) {
util.error('Can not create second element with ID `' + data.id + '`');
// can't create element if one already has that id
removeFromElements();
continue;
}
var id = data.id; // id is finalised, now let's keep a ref
if (_ele.isNode()) {
// extra checks for nodes
var pos = _private.position;
// make sure the nodes have a defined position
if (pos.x == null) {
pos.x = 0;
}
if (pos.y == null) {
pos.y = 0;
}
}
if (_ele.isEdge()) {
// extra checks for edges
var edge = _ele;
var fields = ['source', 'target'];
var fieldsLength = fields.length;
var badSourceOrTarget = false;
for (var j = 0; j < fieldsLength; j++) {
var field = fields[j];
var val = data[field];
if (is.number(val)) {
val = data[field] = '' + data[field]; // now string
}
if (val == null || val === '') {
// can't create if source or target is not defined properly
util.error('Can not create edge `' + id + '` with unspecified ' + field);
badSourceOrTarget = true;
} else if (!cy.hasElementWithId(val)) {
// can't create edge if one of its nodes doesn't exist
util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');
badSourceOrTarget = true;
}
}
if (badSourceOrTarget) {
removeFromElements();continue;
} // can't create this
var src = cy.getElementById(data.source);
var tgt = cy.getElementById(data.target);
src._private.edges.push(edge);
tgt._private.edges.push(edge);
edge._private.source = src;
edge._private.target = tgt;
} // if is edge
// create mock ids / indexes maps for element so it can be used like collections
_private.map = new Map();
_private.map.set(id, { ele: _ele, index: 0 });
_private.removed = false;
cy.addToPool(_ele);
} // for each element
// do compound node sanity checks
for (var _i3 = 0; _i3 < nodes.length; _i3++) {
// each node
var node = nodes[_i3];
var _data = node._private.data;
if (is.number(_data.parent)) {
// then automake string
_data.parent = '' + _data.parent;
}
var parentId = _data.parent;
var specifiedParent = parentId != null;
if (specifiedParent) {
var parent = cy.getElementById(parentId);
if (parent.empty()) {
// non-existant parent; just remove it
_data.parent = undefined;
} else {
var selfAsParent = false;
var ancestor = parent;
while (!ancestor.empty()) {
if (node.same(ancestor)) {
// mark self as parent and remove from data
selfAsParent = true;
_data.parent = undefined; // remove parent reference
// exit or we loop forever
break;
}
ancestor = ancestor.parent();
}
if (!selfAsParent) {
// connect with children
parent[0]._private.children.push(node);
node._private.parent = parent[0];
// let the core know we have a compound graph
cy_p.hasCompoundNodes = true;
}
} // else
} // if specified parent
} // for each node
if (elements.length > 0) {
var restored = new Collection(cy, elements);
for (var _i4 = 0; _i4 < restored.length; _i4++) {
var _ele2 = restored[_i4];
if (_ele2.isNode()) {
continue;
}
// adding an edge invalidates the traversal caches for the parallel edges
_ele2.parallelEdges().clearTraversalCache();
// adding an edge invalidates the traversal cache for the connected nodes
_ele2.source().clearTraversalCache();
_ele2.target().clearTraversalCache();
}
var toUpdateStyle = void 0;
if (cy_p.hasCompoundNodes) {
toUpdateStyle = cy.collection().merge(restored).merge(restored.connectedNodes()).merge(restored.parent());
} else {
toUpdateStyle = restored;
}
toUpdateStyle.dirtyCompoundBoundsCache().updateStyle(notifyRenderer);
if (notifyRenderer) {
restored.emitAndNotify('add');
} else {
restored.emit('add');
}
}
return self; // chainability
};
elesfn.removed = function () {
var ele = this[0];
return ele && ele._private.removed;
};
elesfn.inside = function () {
var ele = this[0];
return ele && !ele._private.removed;
};
elesfn.remove = function (notifyRenderer) {
var self = this;
var removed = [];
var elesToRemove = [];
var elesToRemoveIds = {};
var cy = self._private.cy;
if (notifyRenderer === undefined) {
notifyRenderer = true;
}
// add connected edges
function addConnectedEdges(node) {
var edges = node._private.edges;
for (var i = 0; i < edges.length; i++) {
add(edges[i]);
}
}
// add descendant nodes
function addChildren(node) {
var children = node._private.children;
for (var i = 0; i < children.length; i++) {
add(children[i]);
}
}
function add(ele) {
var alreadyAdded = elesToRemoveIds[ele.id()];
if (ele.removed() || alreadyAdded) {
return;
} else {
elesToRemoveIds[ele.id()] = true;
}
if (ele.isNode()) {
elesToRemove.push(ele); // nodes are removed last
addConnectedEdges(ele);
addChildren(ele);
} else {
elesToRemove.unshift(ele); // edges are removed first
}
}
// make the list of elements to remove
// (may be removing more than specified due to connected edges etc)
for (var i = 0, l = self.length; i < l; i++) {
var ele = self[i];
add(ele);
}
function removeEdgeRef(node, edge) {
var connectedEdges = node._private.edges;
util.removeFromArray(connectedEdges, edge);
// removing an edges invalidates the traversal cache for its nodes
node.clearTraversalCache();
}
function removeParallelRefs(edge) {
// removing an edge invalidates the traversal caches for the parallel edges
edge.parallelEdges().clearTraversalCache();
}
var alteredParents = [];
alteredParents.ids = {};
function removeChildRef(parent, ele) {
ele = ele[0];
parent = parent[0];
var children = parent._private.children;
var pid = parent.id();
util.removeFromArray(children, ele);
if (!alteredParents.ids[pid]) {
alteredParents.ids[pid] = true;
alteredParents.push(parent);
}
}
self.dirtyCompoundBoundsCache();
cy.removeFromPool(elesToRemove); // remove from core pool
for (var _i5 = 0; _i5 < elesToRemove.length; _i5++) {
var _ele3 = elesToRemove[_i5];
// mark as removed
_ele3._private.removed = true;
// add to list of removed elements
removed.push(_ele3);
if (_ele3.isEdge()) {
// remove references to this edge in its connected nodes
var src = _ele3.source()[0];
var tgt = _ele3.target()[0];
removeEdgeRef(src, _ele3);
removeEdgeRef(tgt, _ele3);
removeParallelRefs(_ele3);
} else {
// remove reference to parent
var parent = _ele3.parent();
if (parent.length !== 0) {
removeChildRef(parent, _ele3);
}
}
}
// check to see if we have a compound graph or not
var elesStillInside = cy._private.elements;
cy._private.hasCompoundNodes = false;
for (var _i6 = 0; _i6 < elesStillInside.length; _i6++) {
var _ele4 = elesStillInside[_i6];
if (_ele4.isParent()) {
cy._private.hasCompoundNodes = true;
break;
}
}
var removedElements = new Collection(this.cy(), removed);
if (removedElements.size() > 0) {
// must manually notify since trigger won't do this automatically once removed
if (notifyRenderer) {
this.cy().notify({
type: 'remove',
eles: removedElements
});
}
removedElements.emit('remove');
}
// the parents who were modified by the removal need their style updated
for (var _i7 = 0; _i7 < alteredParents.length; _i7++) {
var _ele5 = alteredParents[_i7];
if (!_ele5.removed()) {
_ele5.updateStyle();
}
}
return new Collection(cy, removed);
};
elesfn.move = function (struct) {
var cy = this._private.cy;
if (struct.source !== undefined || struct.target !== undefined) {
var srcId = struct.source;
var tgtId = struct.target;
var srcExists = cy.hasElementWithId(srcId);
var tgtExists = cy.hasElementWithId(tgtId);
if (srcExists || tgtExists) {
var jsons = this.jsons();
this.remove();
for (var i = 0; i < jsons.length; i++) {
var json = jsons[i];
var ele = this[i];
if (json.group === 'edges') {
if (srcExists) {
json.data.source = srcId;
}
if (tgtExists) {
json.data.target = tgtId;
}
json.scratch = ele._private.scratch;
}
}
return cy.add(jsons);
}
} else if (struct.parent !== undefined) {
// move node to new parent
var parentId = struct.parent;
var parentExists = parentId === null || cy.hasElementWithId(parentId);
if (parentExists) {
var _jsons = this.jsons();
var descs = this.descendants();
var descsEtcJsons = descs.union(descs.union(this).connectedEdges()).jsons();
this.remove(); // NB: also removes descendants and their connected edges
for (var _i8 = 0; _i8 < _jsons.length; _i8++) {
var _json = _jsons[_i8];
var _ele6 = this[_i8];
if (_json.group === 'nodes') {
_json.data.parent = parentId === null ? undefined : parentId;
_json.scratch = _ele6._private.scratch;
}
}
return cy.add(_jsons.concat(descsEtcJsons));
}
}
return this; // if nothing done
};
[__webpack_require__(29), __webpack_require__(43), __webpack_require__(48), __webpack_require__(49), __webpack_require__(54), __webpack_require__(55), __webpack_require__(56), __webpack_require__(57), __webpack_require__(62), __webpack_require__(63), __webpack_require__(64), __webpack_require__(7), __webpack_require__(65), __webpack_require__(66), __webpack_require__(67), __webpack_require__(68), __webpack_require__(69)].forEach(function (props) {
util.extend(elesfn, props);
});
module.exports = Collection;
/***/ }),
/* 8 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
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 _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/* global Set */
var undef = true ? 'undefined' : _typeof(undefined);
var ObjectSet = function () {
function ObjectSet(arrayOrObjectSet) {
_classCallCheck(this, ObjectSet);
this._obj = Object.create(null);
if (arrayOrObjectSet != null) {
var arr = void 0;
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) {
this._obj[val] = 1;
}
}, {
key: 'delete',
value: function _delete(val) {
this._obj[val] = 0;
}
}, {
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);
}
}, {
key: 'size',
get: function get() {
return this.toArray().length;
}
}]);
return ObjectSet;
}();
// TODO use the stdlib Set in future...
// module.exports = typeof Set !== undef ? Set : ObjectSet;
module.exports = ObjectSet;
/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = __webpack_require__(32);
/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// storage for parsed queries
var newQuery = function newQuery() {
return {
classes: [],
colonSelectors: [],
data: [],
group: null,
ids: [],
meta: [],
// fake selectors
collection: null, // a collection to match against
filter: null, // filter function
// these are defined in the upward direction rather than down (e.g. child)
// because we need to go up in Selector.filter()
parent: null, // parent query obj
ancestor: null, // ancestor query obj
subject: null, // defines subject in compound query (subject query obj; points to self if subject)
// use these only when subject has been defined
child: null,
descendant: null
};
};
module.exports = newQuery;
/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var Event = __webpack_require__(16);
var eventRegex = /^([^.]+)(\.(?:[^.]+))?$/; // regex for matching event strings (e.g. "click.namespace")
var universalNamespace = '.*'; // matches as if no namespace specified and prevents users from unbinding accidentally
var defaults = {
qualifierCompare: function qualifierCompare(q1, q2) {
return q1 === q2;
},
eventMatches: function eventMatches() /*context, listener, eventObj*/{
return true;
},
eventFields: function eventFields() /*context*/{
return {};
},
callbackContext: function callbackContext(context /*, listener, eventObj*/) {
return context;
},
beforeEmit: function beforeEmit() /* context, listener, eventObj */{},
afterEmit: function afterEmit() /* context, listener, eventObj */{},
bubble: function bubble() /*context*/{
return false;
},
parent: function parent() /*context*/{
return null;
},
context: undefined
};
function Emitter(opts) {
util.assign(this, defaults, opts);
this.listeners = [];
this.emitting = 0;
}
var p = Emitter.prototype;
var forEachEvent = function forEachEvent(self, handler, events, qualifier, callback, conf, confOverrides) {
if (is.fn(qualifier)) {
callback = qualifier;
qualifier = null;
}
if (confOverrides) {
if (conf == null) {
conf = confOverrides;
} else {
conf = util.assign({}, conf, confOverrides);
}
}
var eventList = events.split(/\s+/);
for (var i = 0; i < eventList.length; i++) {
var evt = eventList[i];
if (is.emptyString(evt)) {
continue;
}
var match = evt.match(eventRegex); // type[.namespace]
if (match) {
var type = match[1];
var namespace = match[2] ? match[2] : null;
var ret = handler(self, evt, type, namespace, qualifier, callback, conf);
if (ret === false) {
break;
} // allow exiting early
}
}
};
var makeEventObj = function makeEventObj(self, obj) {
return new Event(obj.type, util.assign(obj, self.eventFields(self.context)));
};
var forEachEventObj = function forEachEventObj(self, handler, events) {
if (is.event(events)) {
handler(self, events);
return;
} else if (is.plainObject(events)) {
handler(self, makeEventObj(self, events));
return;
}
var eventList = events.split(/\s+/);
for (var i = 0; i < eventList.length; i++) {
var evt = eventList[i];
if (is.emptyString(evt)) {
continue;
}
var match = evt.match(eventRegex); // type[.namespace]
if (match) {
var type = match[1];
var namespace = match[2] ? match[2] : null;
var eventObj = makeEventObj(self, {
type: type,
namespace: namespace,
target: self.context
});
handler(self, eventObj);
}
}
};
p.on = p.addListener = function (events, qualifier, callback, conf, confOverrides) {
forEachEvent(this, function (self, event, type, namespace, qualifier, callback, conf) {
if (is.fn(callback)) {
self.listeners.push({
event: event, // full event string
callback: callback, // callback to run
type: type, // the event type (e.g. 'click')
namespace: namespace, // the event namespace (e.g. ".foo")
qualifier: qualifier, // a restriction on whether to match this emitter
conf: conf // additional configuration
});
}
}, events, qualifier, callback, conf, confOverrides);
return this;
};
p.one = function (events, qualifier, callback, conf) {
return this.on(events, qualifier, callback, conf, { one: true });
};
p.removeListener = p.off = function (events, qualifier, callback, conf) {
var _this = this;
if (this.emitting !== 0) {
this.listeners = util.copyArray(this.listeners);
}
var listeners = this.listeners;
var _loop = function _loop(i) {
var listener = listeners[i];
forEachEvent(_this, function (self, event, type, namespace, qualifier, callback /*, conf*/) {
if (listener.type === type && (!namespace || listener.namespace === namespace) && (!qualifier || self.qualifierCompare(listener.qualifier, qualifier)) && (!callback || listener.callback === callback)) {
listeners.splice(i, 1);
return false;
}
}, events, qualifier, callback, conf);
};
for (var i = listeners.length - 1; i >= 0; i--) {
_loop(i);
}
return this;
};
p.emit = p.trigger = function (events, extraParams, manualCallback) {
var listeners = this.listeners;
var numListenersBeforeEmit = listeners.length;
this.emitting++;
if (!is.array(extraParams)) {
extraParams = [extraParams];
}
forEachEventObj(this, function (self, eventObj) {
if (manualCallback != null) {
listeners = [{
event: eventObj.event,
type: eventObj.type,
namespace: eventObj.namespace,
callback: manualCallback
}];
numListenersBeforeEmit = listeners.length;
}
var _loop2 = function _loop2(i) {
var listener = listeners[i];
if (listener.type === eventObj.type && (!listener.namespace || listener.namespace === eventObj.namespace || listener.namespace === universalNamespace) && self.eventMatches(self.context, listener, eventObj)) {
var args = [eventObj];
if (extraParams != null) {
util.push(args, extraParams);
}
self.beforeEmit(self.context, listener, eventObj);
if (listener.conf && listener.conf.one) {
self.listeners = self.listeners.filter(function (l) {
return l !== listener;
});
}
var context = self.callbackContext(self.context, listener, eventObj);
var ret = listener.callback.apply(context, args);
self.afterEmit(self.context, listener, eventObj);
if (ret === false) {
eventObj.stopPropagation();
eventObj.preventDefault();
}
} // if listener matches
};
for (var i = 0; i < numListenersBeforeEmit; i++) {
_loop2(i);
} // for listener
if (self.bubble(self.context) && !eventObj.isPropagationStopped()) {
self.parent(self.context).emit(eventObj, extraParams);
}
}, events);
this.emitting--;
return this;
};
module.exports = Emitter;
/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var window = __webpack_require__(3);
var util = __webpack_require__(1);
var Collection = __webpack_require__(7);
var is = __webpack_require__(0);
var Promise = __webpack_require__(5);
var define = __webpack_require__(4);
var Core = function Core(opts) {
var cy = this;
opts = util.extend({}, opts);
var container = opts.container;
// allow for passing a wrapped jquery object
// e.g. cytoscape({ container: $('#cy') })
if (container && !is.htmlElement(container) && is.htmlElement(container[0])) {
container = container[0];
}
var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery
reg = reg || {};
if (reg && reg.cy) {
reg.cy.destroy();
reg = {}; // old instance => replace reg completely
}
var readies = reg.readies = reg.readies || [];
if (container) {
container._cyreg = reg;
} // make sure container assoc'd reg points to this cy
reg.cy = cy;
var head = window !== undefined && container !== undefined && !opts.headless;
var options = opts;
options.layout = util.extend({ name: head ? 'grid' : 'null' }, options.layout);
options.renderer = util.extend({ name: head ? 'canvas' : 'null' }, options.renderer);
var defVal = function defVal(def, val, altVal) {
if (val !== undefined) {
return val;
} else if (altVal !== undefined) {
return altVal;
} else {
return def;
}
};
var _p = this._private = {
container: container, // html dom ele container
ready: false, // whether ready has been triggered
options: options, // cached options
elements: new Collection(this), // elements in the graph
listeners: [], // list of listeners
aniEles: new Collection(this), // elements being animated
scratch: {}, // scratch object for core
layout: null,
renderer: null,
destroyed: false, // whether destroy was called
notificationsEnabled: true, // whether notifications are sent to the renderer
minZoom: 1e-50,
maxZoom: 1e50,
zoomingEnabled: defVal(true, options.zoomingEnabled),
userZoomingEnabled: defVal(true, options.userZoomingEnabled),
panningEnabled: defVal(true, options.panningEnabled),
userPanningEnabled: defVal(true, options.userPanningEnabled),
boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),
autolock: defVal(false, options.autolock, options.autolockNodes),
autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),
autounselectify: defVal(false, options.autounselectify),
styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,
zoom: is.number(options.zoom) ? options.zoom : 1,
pan: {
x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0,
y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0
},
animation: { // object for currently-running animations
current: [],
queue: []
},
hasCompoundNodes: false
};
this.createEmitter();
// set selection type
var selType = options.selectionType;
if (selType === undefined || selType !== 'additive' && selType !== 'single') {
// then set default
_p.selectionType = 'single';
} else {
_p.selectionType = selType;
}
// init zoom bounds
if (is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom) {
_p.minZoom = options.minZoom;
_p.maxZoom = options.maxZoom;
} else if (is.number(options.minZoom) && options.maxZoom === undefined) {
_p.minZoom = options.minZoom;
} else if (is.number(options.maxZoom) && options.minZoom === undefined) {
_p.maxZoom = options.maxZoom;
}
var loadExtData = function loadExtData(extData, next) {
var anyIsPromise = extData.some(is.promise);
if (anyIsPromise) {
return Promise.all(extData).then(next); // load all data asynchronously, then exec rest of init
} else {
next(extData); // exec synchronously for convenience
}
};
// start with the default stylesheet so we have something before loading an external stylesheet
if (_p.styleEnabled) {
cy.setStyle([]);
}
// create the renderer
cy.initRenderer(util.extend({
hideEdgesOnViewport: options.hideEdgesOnViewport,
textureOnViewport: options.textureOnViewport,
wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1,
motionBlur: options.motionBlur === undefined ? false : options.motionBlur, // off by default
motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity,
pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : undefined,
desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold,
touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold
}, options.renderer));
var setElesAndLayout = function setElesAndLayout(elements, onload, ondone) {
cy.notifications(false);
// remove old elements
var oldEles = cy.mutableElements();
if (oldEles.length > 0) {
oldEles.remove();
}
if (elements != null) {
if (is.plainObject(elements) || is.array(elements)) {
cy.add(elements);
}
}
cy.one('layoutready', function (e) {
cy.notifications(true);
cy.emit(e); // we missed this event by turning notifications off, so pass it on
cy.notify({
type: 'load',
eles: cy.mutableElements()
});
cy.one('load', onload);
cy.emit('load');
}).one('layoutstop', function () {
cy.one('done', ondone);
cy.emit('done');
});
var layoutOpts = util.extend({}, cy._private.options.layout);
layoutOpts.eles = cy.elements();
cy.layout(layoutOpts).run();
};
loadExtData([options.style, options.elements], function (thens) {
var initStyle = thens[0];
var initEles = thens[1];
// init style
if (_p.styleEnabled) {
cy.style().append(initStyle);
}
// initial load
setElesAndLayout(initEles, function () {
// onready
cy.startAnimationLoop();
_p.ready = true;
// if a ready callback is specified as an option, the bind it
if (is.fn(options.ready)) {
cy.on('ready', options.ready);
}
// bind all the ready handlers registered before creating this instance
for (var i = 0; i < readies.length; i++) {
var fn = readies[i];
cy.on('ready', fn);
}
if (reg) {
reg.readies = [];
} // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc
cy.emit('ready');
}, options.done);
});
};
var corefn = Core.prototype; // short alias
util.extend(corefn, {
instanceString: function instanceString() {
return 'core';
},
isReady: function isReady() {
return this._private.ready;
},
isDestroyed: function isDestroyed() {
return this._private.destroyed;
},
ready: function ready(fn) {
if (this.isReady()) {
this.emitter().emit('ready', [], fn); // just calls fn as though triggered via ready event
} else {
this.on('ready', fn);
}
return this;
},
destroy: function destroy() {
var cy = this;
if (cy.isDestroyed()) return;
cy.stopAnimationLoop();
cy.destroyRenderer();
this.emit('destroy');
cy._private.destroyed = true;
return cy;
},
hasElementWithId: function hasElementWithId(id) {
return this._private.elements.hasElementWithId(id);
},
getElementById: function getElementById(id) {
return this._private.elements.getElementById(id);
},
selectionType: function selectionType() {
return this._private.selectionType;
},
hasCompoundNodes: function hasCompoundNodes() {
return this._private.hasCompoundNodes;
},
headless: function headless() {
return this._private.options.renderer.name === 'null';
},
styleEnabled: function styleEnabled() {
return this._private.styleEnabled;
},
addToPool: function addToPool(eles) {
this._private.elements.merge(eles);
return this; // chaining
},
removeFromPool: function removeFromPool(eles) {
this._private.elements.unmerge(eles);
return this;
},
container: function container() {
return this._private.container;
},
options: function options() {
return util.copy(this._private.options);
},
json: function json(obj) {
var cy = this;
var _p = cy._private;
var eles = cy.mutableElements();
if (is.plainObject(obj)) {
// set
cy.startBatch();
if (obj.elements) {
var idInJson = {};
var updateEles = function updateEles(jsons, gr) {
var toAdd = [];
for (var i = 0; i < jsons.length; i++) {
var json = jsons[i];
var id = json.data.id;
var ele = cy.getElementById(id);
idInJson[id] = true;
if (ele.length !== 0) {
// existing element should be updated
ele.json(json);
} else {
// otherwise should be added
if (gr) {
toAdd.push(util.extend({ group: gr }, json));
} else {
toAdd.push(json);
}
}
}
cy.add(toAdd);
};
if (is.array(obj.elements)) {
// elements: []
updateEles(obj.elements);
} else {
// elements: { nodes: [], edges: [] }
var grs = ['nodes', 'edges'];
for (var i = 0; i < grs.length; i++) {
var gr = grs[i];
var elements = obj.elements[gr];
if (is.array(elements)) {
updateEles(elements, gr);
}
}
}
// elements not specified in json should be removed
eles.stdFilter(function (ele) {
return !idInJson[ele.id()];
}).remove();
}
if (obj.style) {
cy.style(obj.style);
}
if (obj.zoom != null && obj.zoom !== _p.zoom) {
cy.zoom(obj.zoom);
}
if (obj.pan) {
if (obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y) {
cy.pan(obj.pan);
}
}
var fields = ['minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled', 'panningEnabled', 'userPanningEnabled', 'boxSelectionEnabled', 'autolock', 'autoungrabify', 'autounselectify'];
for (var _i = 0; _i < fields.length; _i++) {
var f = fields[_i];
if (obj[f] != null) {
cy[f](obj[f]);
}
}
cy.endBatch();
return this; // chaining
} else if (obj === undefined) {
// get
var json = {};
json.elements = {};
eles.forEach(function (ele) {
var group = ele.group();
if (!json.elements[group]) {
json.elements[group] = [];
}
json.elements[group].push(ele.json());
});
if (this._private.styleEnabled) {
json.style = cy.style().json();
}
json.zoomingEnabled = cy._private.zoomingEnabled;
json.userZoomingEnabled = cy._private.userZoomingEnabled;
json.zoom = cy._private.zoom;
json.minZoom = cy._private.minZoom;
json.maxZoom = cy._private.maxZoom;
json.panningEnabled = cy._private.panningEnabled;
json.userPanningEnabled = cy._private.userPanningEnabled;
json.pan = util.copy(cy._private.pan);
json.boxSelectionEnabled = cy._private.boxSelectionEnabled;
json.renderer = util.copy(cy._private.options.renderer);
json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport;
json.textureOnViewport = cy._private.options.textureOnViewport;
json.wheelSensitivity = cy._private.options.wheelSensitivity;
json.motionBlur = cy._private.options.motionBlur;
return json;
}
},
scratch: define.data({
field: 'scratch',
bindingEvent: 'scratch',
allowBinding: true,
allowSetting: true,
settingEvent: 'scratch',
settingTriggersEvent: true,
triggerFnName: 'trigger',
allowGetting: true
}),
removeScratch: define.removeData({
field: 'scratch',
event: 'scratch',
triggerFnName: 'trigger',
triggerEvent: true
})
});
corefn.$id = corefn.getElementById;
[__webpack_require__(70), __webpack_require__(71), __webpack_require__(79), __webpack_require__(80), __webpack_require__(81), __webpack_require__(82), __webpack_require__(83), __webpack_require__(84), __webpack_require__(85), __webpack_require__(94)].forEach(function (props) {
util.extend(corefn, props);
});
module.exports = Core;
/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = 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 = void 0;
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;
};
/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var Set = __webpack_require__(8);
// represents a node or an edge
var Element = function Element(cy, params, restore) {
restore = restore === undefined || restore ? true : false;
if (cy === undefined || params === undefined || !is.core(cy)) {
util.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') {
util.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, 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
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
active: false, // whether the element is active from user interaction
classes: new Set(), // 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: null, // parent ref
traversalCache: {}, // cache of output of traversal functions
backgrounding: false // whether background images are loading
};
// 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
};
}
if (is.string(params.classes)) {
var 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);
}
}
if (params.style || params.css) {
cy.style().applyBypass(this, params.style || params.css);
}
this.createEmitter();
if (restore === undefined || restore) {
this.restore();
}
};
module.exports = Element;
/***/ }),
/* 15 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var stateSelectors = [{
selector: ':selected',
matches: function matches(ele) {
return ele.selected();
}
}, {
selector: ':unselected',
matches: function matches(ele) {
return !ele.selected();
}
}, {
selector: ':selectable',
matches: function matches(ele) {
return ele.selectable();
}
}, {
selector: ':unselectable',
matches: function matches(ele) {
return !ele.selectable();
}
}, {
selector: ':locked',
matches: function matches(ele) {
return ele.locked();
}
}, {
selector: ':unlocked',
matches: function matches(ele) {
return !ele.locked();
}
}, {
selector: ':visible',
matches: function matches(ele) {
return ele.visible();
}
}, {
selector: ':hidden',
matches: function matches(ele) {
return !ele.visible();
}
}, {
selector: ':transparent',
matches: function matches(ele) {
return ele.transparent();
}
}, {
selector: ':grabbed',
matches: function matches(ele) {
return ele.grabbed();
}
}, {
selector: ':free',
matches: function matches(ele) {
return !ele.grabbed();
}
}, {
selector: ':removed',
matches: function matches(ele) {
return ele.removed();
}
}, {
selector: ':inside',
matches: function matches(ele) {
return !ele.removed();
}
}, {
selector: ':grabbable',
matches: function matches(ele) {
return ele.grabbable();
}
}, {
selector: ':ungrabbable',
matches: function matches(ele) {
return !ele.grabbable();
}
}, {
selector: ':animated',
matches: function matches(ele) {
return ele.animated();
}
}, {
selector: ':unanimated',
matches: function matches(ele) {
return !ele.animated();
}
}, {
selector: ':parent',
matches: function matches(ele) {
return ele.isParent();
}
}, {
selector: ':childless',
matches: function matches(ele) {
return ele.isChildless();
}
}, {
selector: ':child',
matches: function matches(ele) {
return ele.isChild();
}
}, {
selector: ':orphan',
matches: function matches(ele) {
return ele.isOrphan();
}
}, {
selector: ':nonorphan',
matches: function matches(ele) {
return ele.isChild();
}
}, {
selector: ':loop',
matches: function matches(ele) {
return ele.isLoop();
}
}, {
selector: ':simple',
matches: function matches(ele) {
return ele.isSimple();
}
}, {
selector: ':active',
matches: function matches(ele) {
return ele.active();
}
}, {
selector: ':inactive',
matches: function matches(ele) {
return !ele.active();
}
}, {
selector: ':backgrounding',
matches: function matches(ele) {
return ele.backgrounding();
}
}, {
selector: ':nonbackgrounding',
matches: function matches(ele) {
return !ele.backgrounding();
}
}].sort(function (a, b) {
// n.b. selectors that are starting substrings of others must have the longer ones first
return util.sort.descending(a.selector, b.selector);
});
var stateSelectorMatches = function stateSelectorMatches(sel, ele) {
var lookup = stateSelectorMatches.lookup = stateSelectorMatches.lookup || function () {
var selToFn = {};
var s = void 0;
for (var i = 0; i < stateSelectors.length; i++) {
s = stateSelectors[i];
selToFn[s.selector] = s.matches;
}
return selToFn;
}();
return lookup[sel](ele);
};
var stateSelectorRegex = '(' + stateSelectors.map(function (s) {
return s.selector;
}).join('|') + ')';
module.exports = { stateSelectors: stateSelectors, stateSelectorMatches: stateSelectorMatches, stateSelectorRegex: stateSelectorRegex };
/***/ }),
/* 16 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*!
Event object based on jQuery events, MIT license
https://jquery.org/license/
https://tldrlegal.com/license/mit-license
https://github.com/jquery/jquery/blob/master/src/event.js
*/
var Event = function Event(src, props) {
this.recycle(src, props);
};
function returnFalse() {
return false;
}
function returnTrue() {
return true;
}
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
Event.prototype = {
instanceString: function instanceString() {
return 'event';
},
recycle: function recycle(src, props) {
this.isImmediatePropagationStopped = this.isPropagationStopped = this.isDefaultPrevented = returnFalse;
if (src != null && src.preventDefault) {
// Browser Event object
this.type = src.type;
// Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = src.defaultPrevented ? returnTrue : returnFalse;
} else if (src != null && src.type) {
// Plain object containing all event details
props = src;
} else {
// Event string
this.type = src;
}
// Put explicitly provided properties onto the event object
if (props != null) {
// more efficient to manually copy fields we use
this.originalEvent = props.originalEvent;
this.type = props.type != null ? props.type : this.type;
this.cy = props.cy;
this.target = props.target;
this.position = props.position;
this.renderedPosition = props.renderedPosition;
this.namespace = props.namespace;
this.layout = props.layout;
}
if (this.cy != null && this.position != null && this.renderedPosition == null) {
// create a rendered position based on the passed position
var pos = this.position;
var zoom = this.cy.zoom();
var pan = this.cy.pan();
this.renderedPosition = {
x: pos.x * zoom + pan.x,
y: pos.y * zoom + pan.y
};
}
// Create a timestamp if incoming event doesn't have one
this.timeStamp = src && src.timeStamp || Date.now();
},
preventDefault: function preventDefault() {
this.isDefaultPrevented = returnTrue;
var e = this.originalEvent;
if (!e) {
return;
}
// if preventDefault exists run it on the original event
if (e.preventDefault) {
e.preventDefault();
}
},
stopPropagation: function stopPropagation() {
this.isPropagationStopped = returnTrue;
var e = this.originalEvent;
if (!e) {
return;
}
// if stopPropagation exists run it on the original event
if (e.stopPropagation) {
e.stopPropagation();
}
},
stopImmediatePropagation: function stopImmediatePropagation() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
},
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse
};
module.exports = Event;
/***/ }),
/* 17 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/**
* Elements are drawn in a specific order based on compound depth (low to high), the element type (nodes above edges),
* and z-index (low to high). These styles affect how this applies:
*
* z-compound-depth: May be `bottom | orphan | auto | top`. The first drawn is `bottom`, then `orphan` which is the
* same depth as the root of the compound graph, followed by the default value `auto` which draws in order from
* root to leaves of the compound graph. The last drawn is `top`.
* z-index-compare: May be `auto | manual`. The default value is `auto` which always draws edges under nodes.
* `manual` ignores this convention and draws based on the `z-index` value setting.
* z-index: An integer value that affects the relative draw order of elements. In general, an element with a higher
* `z-index` will be drawn on top of an element with a lower `z-index`.
*/
var util = __webpack_require__(1);
var zIndexSort = function zIndexSort(a, b) {
var cy = a.cy();
var hasCompoundNodes = cy.hasCompoundNodes();
function getDepth(ele) {
var style = ele.pstyle('z-compound-depth');
if (style.value === 'auto') {
return hasCompoundNodes ? ele.zDepth() : 0;
} else if (style.value === 'bottom') {
return -1;
} else if (style.value === 'top') {
return util.MAX_INT;
}
// 'orphan'
return 0;
}
var depthDiff = getDepth(a) - getDepth(b);
if (depthDiff !== 0) {
return depthDiff;
}
function getEleDepth(ele) {
var style = ele.pstyle('z-index-compare');
if (style.value === 'auto') {
return ele.isNode() ? 1 : 0;
}
// 'manual'
return 0;
}
var eleDiff = getEleDepth(a) - getEleDepth(b);
if (eleDiff !== 0) {
return eleDiff;
}
var zDiff = a.pstyle('z-index').value - b.pstyle('z-index').value;
if (zDiff !== 0) {
return zDiff;
}
// compare indices in the core (order added to graph w/ last on top)
return a.poolIndex() - b.poolIndex();
};
module.exports = zIndexSort;
/***/ }),
/* 18 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Selector = __webpack_require__(6);
var Style = function Style(cy) {
if (!(this instanceof Style)) {
return new Style(cy);
}
if (!is.core(cy)) {
util.error('A style must have a core reference');
return;
}
this._private = {
cy: cy,
coreStyle: {}
};
this.length = 0;
this.resetToDefault();
};
var styfn = Style.prototype;
styfn.instanceString = function () {
return 'style';
};
// remove all contexts
styfn.clear = function () {
for (var i = 0; i < this.length; i++) {
this[i] = undefined;
}
this.length = 0;
var _p = this._private;
_p.newStyle = true;
return this; // chaining
};
styfn.resetToDefault = function () {
this.clear();
this.addDefaultStylesheet();
return this;
};
// builds a style object for the 'core' selector
styfn.core = function () {
return this._private.coreStyle;
};
// create a new context from the specified selector string and switch to that context
styfn.selector = function (selectorStr) {
// 'core' is a special case and does not need a selector
var selector = selectorStr === 'core' ? null : new Selector(selectorStr);
var i = this.length++; // new context means new index
this[i] = {
selector: selector,
properties: [],
mappedProperties: [],
index: i
};
return this; // chaining
};
// add one or many css rules to the current context
styfn.css = function () {
var self = this;
var args = arguments;
switch (args.length) {
case 1:
var map = args[0];
for (var i = 0; i < self.properties.length; i++) {
var prop = self.properties[i];
var mapVal = map[prop.name];
if (mapVal === undefined) {
mapVal = map[util.dash2camel(prop.name)];
}
if (mapVal !== undefined) {
this.cssRule(prop.name, mapVal);
}
}
break;
case 2:
this.cssRule(args[0], args[1]);
break;
default:
break; // do nothing if args are invalid
}
return this; // chaining
};
styfn.style = styfn.css;
// add a single css rule to the current context
styfn.cssRule = function (name, value) {
// name-value pair
var property = this.parse(name, value);
// add property to current context if valid
if (property) {
var i = this.length - 1;
this[i].properties.push(property);
this[i].properties[property.name] = property; // allow access by name as well
if (property.name.match(/pie-(\d+)-background-size/) && property.value) {
this._private.hasPie = true;
}
if (property.mapped) {
this[i].mappedProperties.push(property);
}
// add to core style if necessary
var currentSelectorIsCore = !this[i].selector;
if (currentSelectorIsCore) {
this._private.coreStyle[property.name] = property;
}
}
return this; // chaining
};
styfn.append = function (style) {
if (is.stylesheet(style)) {
style.appendToStyle(this);
} else if (is.array(style)) {
this.appendFromJson(style);
} else if (is.string(style)) {
this.appendFromString(style);
} // you probably wouldn't want to append a Style, since you'd duplicate the default parts
return this;
};
// static function
Style.fromJson = function (cy, json) {
var style = new Style(cy);
style.fromJson(json);
return style;
};
Style.fromString = function (cy, string) {
return new Style(cy).fromString(string);
};
[__webpack_require__(86), __webpack_require__(87), __webpack_require__(88), __webpack_require__(89), __webpack_require__(90), __webpack_require__(91), __webpack_require__(92), __webpack_require__(93)].forEach(function (props) {
util.extend(styfn, props);
});
Style.types = styfn.types;
Style.properties = styfn.properties;
module.exports = Style;
/***/ }),
/* 19 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var fullFpsTime = 1000 / 60; // assume 60 frames per second
module.exports = {
setupDequeueing: function setupDequeueing(opts) {
return function setupDequeueingImpl() {
var self = this;
var r = this.renderer;
if (self.dequeueingSetup) {
return;
} else {
self.dequeueingSetup = true;
}
var queueRedraw = util.debounce(function () {
r.redrawHint('eles', true);
r.redrawHint('drag', true);
r.redraw();
}, opts.deqRedrawThreshold);
var dequeue = function dequeue(willDraw, frameStartTime) {
var startTime = util.performanceNow();
var avgRenderTime = r.averageRedrawTime;
var renderTime = r.lastRedrawTime;
var deqd = [];
var extent = r.cy.extent();
var pixelRatio = r.getPixelRatio();
while (true) {
var now = util.performanceNow();
var duration = now - startTime;
var frameDuration = now - frameStartTime;
if (renderTime < fullFpsTime) {
// if we're rendering faster than the ideal fps, then do dequeueing
// during all of the remaining frame time
var timeAvailable = fullFpsTime - (willDraw ? avgRenderTime : 0);
if (frameDuration >= opts.deqFastCost * timeAvailable) {
break;
}
} else {
if (willDraw) {
if (duration >= opts.deqCost * renderTime || duration >= opts.deqAvgCost * avgRenderTime) {
break;
}
} else if (frameDuration >= opts.deqNoDrawCost * fullFpsTime) {
break;
}
}
var thisDeqd = opts.deq(self, pixelRatio, extent);
if (thisDeqd.length > 0) {
for (var i = 0; i < thisDeqd.length; i++) {
deqd.push(thisDeqd[i]);
}
} else {
break;
}
}
// callbacks on dequeue
if (deqd.length > 0) {
opts.onDeqd(self, deqd);
if (!willDraw && opts.shouldRedraw(self, deqd, pixelRatio, extent)) {
queueRedraw();
}
}
};
var priority = opts.priority || util.noop;
r.beforeRender(dequeue, priority(self));
};
}
};
/***/ }),
/* 20 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Core = __webpack_require__(12);
var extension = __webpack_require__(95);
var Stylesheet = __webpack_require__(137);
var cytoscape = function cytoscape(options) {
// jshint ignore:line
// if no options specified, use default
if (options === undefined) {
options = {};
}
// create instance
if (is.plainObject(options)) {
return new Core(options);
}
// allow for registration of extensions
else if (is.string(options)) {
return extension.apply(extension, arguments);
}
};
// e.g. cytoscape.use( require('cytoscape-foo'), bar )
cytoscape.use = function (ext) {
var args = Array.prototype.slice.call(arguments, 1); // args to pass to ext
args.unshift(cytoscape); // cytoscape is first arg to ext
ext.apply(null, args);
return this;
};
// replaced by build system
cytoscape.version = __webpack_require__(138);
// expose public apis (mostly for extensions)
cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;
module.exports = cytoscape;
/***/ }),
/* 21 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
module.exports = {
// get [r, g, b] from #abc or #aabbcc
hex2tuple: function hex2tuple(hex) {
if (!(hex.length === 4 || hex.length === 7) || hex[0] !== '#') {
return;
}
var shortHex = hex.length === 4;
var r = void 0,
g = void 0,
b = void 0;
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)
hsl2tuple: function hsl2tuple(hsl) {
var ret = void 0;
var h = void 0,
s = void 0,
l = void 0,
a = void 0,
r = void 0,
g = void 0,
b = void 0;
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('^' + this.regex.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)
rgb2tuple: function rgb2tuple(rgb) {
var ret = void 0;
var m = new RegExp('^' + this.regex.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;
},
colorname2tuple: function colorname2tuple(color) {
return this.colors[color.toLowerCase()];
},
color2tuple: function color2tuple(color) {
return (is.array(color) ? color : null) || this.colorname2tuple(color) || this.hex2tuple(color) || this.rgb2tuple(color) || this.hsl2tuple(color);
},
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]
}
};
/***/ }),
/* 22 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
module.exports = {
// has anything been set in the map
mapEmpty: function mapEmpty(map) {
var empty = true;
if (map != null) {
return Object.keys(map).length === 0;
}
return empty;
},
// pushes to the array at the end of a map (map may not be built)
pushMap: function pushMap(options) {
var array = this.getMap(options);
if (array == null) {
// if empty, put initial array
this.setMap(this.extend({}, options, {
value: [options.value]
}));
} else {
array.push(options.value);
}
},
// sets the value in a map (map may not be built)
setMap: function setMap(options) {
var obj = options.map;
var key = void 0;
var keys = options.keys;
var l = keys.length;
for (var i = 0; i < l; i++) {
var _key = keys[i];
if (is.plainObject(_key)) {
this.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
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 (is.plainObject(key)) {
this.error('Tried to get map with object key');
}
obj = obj[key];
if (obj == null) {
return obj;
}
}
return obj;
},
// deletes the entry in the map
deleteMap: function deleteMap(options) {
var obj = options.map;
var keys = options.keys;
var l = keys.length;
var keepChildren = options.keepChildren;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (is.plainObject(key)) {
this.error('Tried to delete map with object key');
}
var lastKey = i === options.keys.length - 1;
if (lastKey) {
if (keepChildren) {
// then only delete child fields not in keepChildren
var children = Object.keys(obj);
for (var j = 0; j < children.length; j++) {
var child = children[j];
if (!keepChildren[child]) {
obj[child] = undefined;
}
}
} else {
obj[key] = undefined;
}
} else {
obj = obj[key];
}
}
}
};
/***/ }),
/* 23 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
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}';
module.exports = {
regex: {
number: number,
rgba: rgba,
rgbaNoBackRefs: rgbaNoBackRefs,
hsla: hsla,
hslaNoBackRefs: hslaNoBackRefs,
hex3: hex3,
hex6: hex6
}
};
/***/ }),
/* 24 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var memoize = __webpack_require__(13);
var is = __webpack_require__(0);
module.exports = {
camel2dash: memoize(function (str) {
return str.replace(/([A-Z])/g, function (v) {
return '-' + v.toLowerCase();
});
}),
dash2camel: memoize(function (str) {
return str.replace(/(-\w)/g, function (v) {
return v[1].toUpperCase();
});
}),
prependCamel: memoize(function (prefix, str) {
return prefix + str[0].toUpperCase() + str.substring(1);
}, function (prefix, str) {
return prefix + '$' + str;
}),
capitalize: function capitalize(str) {
if (is.emptyString(str)) {
return str;
}
return str.charAt(0).toUpperCase() + str.substring(1);
}
};
/***/ }),
/* 25 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var window = __webpack_require__(3);
var performance = window ? window.performance : null;
var util = {};
var pnow = performance && performance.now ? function () {
return performance.now();
} : function () {
return Date.now();
};
var raf = function () {
if (window) {
if (window.requestAnimationFrame) {
return function (fn) {
window.requestAnimationFrame(fn);
};
} else if (window.mozRequestAnimationFrame) {
return function (fn) {
window.mozRequestAnimationFrame(fn);
};
} else if (window.webkitRequestAnimationFrame) {
return function (fn) {
window.webkitRequestAnimationFrame(fn);
};
} else if (window.msRequestAnimationFrame) {
return function (fn) {
window.msRequestAnimationFrame(fn);
};
}
}
return function (fn) {
if (fn) {
setTimeout(function () {
fn(pnow());
}, 1000 / 60);
}
};
}();
util.requestAnimationFrame = function (fn) {
raf(fn);
};
util.performanceNow = pnow;
util.debounce = __webpack_require__(26);
util.now = function () {
return Date.now();
};
module.exports = util;
/***/ }),
/* 26 */
/***/ (function(module, exports) {
/**
* lodash (Custom Build) <https://lodash.com/>
* Build: `lodash modularize exports="npm" -o ./`
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';
/** Used as references for various `Number` constants. */
var NAN = 0 / 0;
/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';
/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Used for built-in method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var objectToString = objectProto.toString;
/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Date
* @returns {number} Returns the timestamp.
* @example
*
* _.defer(function(stamp) {
* console.log(_.now() - stamp);
* }, _.now());
* // => Logs the number of milliseconds it took for the deferred invocation.
*/
var now = function() {
return root.Date.now();
};
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. The debounced function comes with a `cancel` method to cancel
* delayed `func` invocations and a `flush` method to immediately invoke them.
* Provide `options` to indicate whether `func` should be invoked on the
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
* with the last arguments provided to the debounced function. Subsequent
* calls to the debounced function return the result of the last `func`
* invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to debounce.
* @param {number} [wait=0] The number of milliseconds to delay.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=false]
* Specify invoking on the leading edge of the timeout.
* @param {number} [options.maxWait]
* The maximum time `func` is allowed to be delayed before it's invoked.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // Avoid costly calculations while the window size is in flux.
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
* jQuery(element).on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
* var source = new EventSource('/stream');
* jQuery(source).on('message', debounced);
*
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
result,
timerId,
lastCallTime,
lastInvokeTime = 0,
leading = false,
maxing = false,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs,
thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time;
// Start the timer for the trailing edge.
timerId = setTimeout(timerExpired, wait);
// Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime,
result = wait - timeSinceLastCall;
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/
function isObject(value) {
var type = typeof value;
return !!value && (type == 'object' || type == 'function');
}
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return !!value && typeof value == 'object';
}
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/
function isSymbol(value) {
return typeof value == 'symbol' ||
(isObjectLike(value) && objectToString.call(value) == symbolTag);
}
/**
* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
module.exports = debounce;
/***/ }),
/* 27 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function ascending(a, b) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
function descending(a, b) {
return -1 * ascending(a, b);
}
module.exports = {
sort: {
ascending: ascending,
descending: descending
}
};
/***/ }),
/* 28 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function ObjectMap() {
this._obj = {};
}
var p = ObjectMap.prototype;
p.set = function (key, val) {
this._obj[key] = val;
};
p.delete = function (key) {
this._obj[key] = null;
};
p.has = function (key) {
return this._obj[key] != null;
};
p.get = function (key) {
return this._obj[key];
};
// TODO use the stdlib Map in future...
// module.exports = typeof Map !== 'undefined' ? Map : ObjectMap;
module.exports = ObjectMap;
/***/ }),
/* 29 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var elesfn = {};
[__webpack_require__(30), __webpack_require__(31), __webpack_require__(34), __webpack_require__(35), __webpack_require__(36), __webpack_require__(37), __webpack_require__(38), __webpack_require__(39), __webpack_require__(40), __webpack_require__(41), __webpack_require__(42)].forEach(function (props) {
util.extend(elesfn, props);
});
module.exports = elesfn;
/***/ }),
/* 30 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
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 (is.plainObject(roots) && !is.elementOrCollection(roots)) {
options = roots;
roots = options.roots || options.root;
fn = options.visit;
directed = options.directed;
}
directed = arguments.length === 2 && !is.fn(fn) ? fn : directed;
fn = is.fn(fn) ? fn : function () {};
var cy = this._private.cy;
var v = roots = is.string(roots) ? this.filter(roots) : roots;
var Q = [];
var connectedNodes = [];
var connectedBy = {};
var id2depth = {};
var V = {};
var j = 0;
var found;
var nodes = this.nodes();
var edges = this.edges();
// enqueue v
for (var i = 0; i < v.length; i++) {
if (v[i].isNode()) {
Q.unshift(v[i]);
if (params.bfs) {
V[v[i].id()] = true;
connectedNodes.push(v[i]);
}
id2depth[v[i].id()] = 0;
}
}
while (Q.length !== 0) {
var v = params.bfs ? Q.shift() : Q.pop();
if (params.dfs) {
if (V[v.id()]) {
continue;
}
V[v.id()] = true;
connectedNodes.push(v);
}
var depth = id2depth[v.id()];
var prevEdge = connectedBy[v.id()];
var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not(v)[0];
var ret;
ret = fn(v, prevEdge, prevNode, j++, depth);
if (ret === true) {
found = v;
break;
}
if (ret === false) {
break;
}
var vwEdges = v.connectedEdges(directed ? function (ele) {
return ele.data('source') === v.id();
} : undefined).intersect(edges);
for (var i = 0; i < vwEdges.length; i++) {
var e = vwEdges[i];
var w = e.connectedNodes(function (n) {
return n.id() !== v.id();
}).intersect(nodes);
if (w.length !== 0 && !V[w.id()]) {
w = w[0];
Q.push(w);
if (params.bfs) {
V[w.id()] = true;
connectedNodes.push(w);
}
connectedBy[w.id()] = e;
id2depth[w.id()] = id2depth[v.id()] + 1;
}
}
}
var connectedEles = [];
for (var i = 0; i < connectedNodes.length; i++) {
var node = connectedNodes[i];
var edge = connectedBy[node.id()];
if (edge) {
connectedEles.push(edge);
}
connectedEles.push(node);
}
return {
path: cy.collection(connectedEles, { unique: true }),
found: cy.collection(found)
};
};
};
// search, spanning trees, etc
var elesfn = {
breadthFirstSearch: defineSearch({ bfs: true }),
depthFirstSearch: defineSearch({ dfs: true })
};
// nice, short mathemathical alias
elesfn.bfs = elesfn.breadthFirstSearch;
elesfn.dfs = elesfn.depthFirstSearch;
module.exports = elesfn;
/***/ }),
/* 31 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Heap = __webpack_require__(9);
var elesfn = {
dijkstra: function dijkstra(root, weightFn, directed) {
var options;
if (is.plainObject(root) && !is.elementOrCollection(root)) {
options = root;
root = options.root;
weightFn = options.weight;
directed = options.directed;
}
var cy = this._private.cy;
weightFn = is.fn(weightFn) ? weightFn : function () {
return 1;
}; // if not specified, assume each edge has equal weight (1)
var source = is.string(root) ? this.filter(root)[0] : root[0];
var dist = {};
var prev = {};
var knownDist = {};
var edges = this.edges().filter(function (ele) {
return !ele.isLoop();
});
var nodes = this.nodes();
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(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 i = 0; i < neighbors.length; i++) {
var v = neighbors[i];
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 = is.string(node) ? nodes.filter(node)[0] : node[0];
return knownDist[target.id()];
},
pathTo: function pathTo(node) {
var target = is.string(node) ? nodes.filter(node)[0] : node[0];
var S = [];
var u = target;
if (target.length > 0) {
S.unshift(target);
while (prev[u.id()]) {
var p = prev[u.id()];
S.unshift(p.edge);
S.unshift(p.node);
u = p.node;
}
}
return cy.collection(S);
}
};
}
};
module.exports = elesfn;
/***/ }),
/* 32 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(33);
/***/ }),
/* 33 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Generated by CoffeeScript 1.8.0
(function() {
var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;
floor = Math.floor, min = Math.min;
/*
Default comparison function to be used
*/
defaultCmp = function(x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
};
/*
Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the right of the rightmost x.
Optional args lo (default 0) and hi (default a.length) bound the slice
of a to be searched.
*/
insort = function(a, x, lo, hi, cmp) {
var mid;
if (lo == null) {
lo = 0;
}
if (cmp == null) {
cmp = defaultCmp;
}
if (lo < 0) {
throw new Error('lo must be non-negative');
}
if (hi == null) {
hi = a.length;
}
while (lo < hi) {
mid = floor((lo + hi) / 2);
if (cmp(x, a[mid]) < 0) {
hi = mid;
} else {
lo = mid + 1;
}
}
return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);
};
/*
Push item onto heap, maintaining the heap invariant.
*/
heappush = function(array, item, cmp) {
if (cmp == null) {
cmp = defaultCmp;
}
array.push(item);
return _siftdown(array, 0, array.length - 1, cmp);
};
/*
Pop the smallest item off the heap, maintaining the heap invariant.
*/
heappop = function(array, cmp) {
var lastelt, returnitem;
if (cmp == null) {
cmp = defaultCmp;
}
lastelt = array.pop();
if (array.length) {
returnitem = array[0];
array[0] = lastelt;
_siftup(array, 0, cmp);
} else {
returnitem = lastelt;
}
return returnitem;
};
/*
Pop and return the current smallest value, and add the new item.
This is more efficient than heappop() followed by heappush(), and can be
more appropriate when using a fixed size heap. Note that the value
returned may be larger than item! That constrains reasonable use of
this routine unless written as part of a conditional replacement:
if item > array[0]
item = heapreplace(array, item)
*/
heapreplace = function(array, item, cmp) {
var returnitem;
if (cmp == null) {
cmp = defaultCmp;
}
returnitem = array[0];
array[0] = item;
_siftup(array, 0, cmp);
return returnitem;
};
/*
Fast version of a heappush followed by a heappop.
*/
heappushpop = function(array, item, cmp) {
var _ref;
if (cmp == null) {
cmp = defaultCmp;
}
if (array.length && cmp(array[0], item) < 0) {
_ref = [array[0], item], item = _ref[0], array[0] = _ref[1];
_siftup(array, 0, cmp);
}
return item;
};
/*
Transform list into a heap, in-place, in O(array.length) time.
*/
heapify = function(array, cmp) {
var i, _i, _j, _len, _ref, _ref1, _results, _results1;
if (cmp == null) {
cmp = defaultCmp;
}
_ref1 = (function() {
_results1 = [];
for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }
return _results1;
}).apply(this).reverse();
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
i = _ref1[_i];
_results.push(_siftup(array, i, cmp));
}
return _results;
};
/*
Update the position of the given item in the heap.
This function should be called every time the item is being modified.
*/
updateItem = function(array, item, cmp) {
var pos;
if (cmp == null) {
cmp = defaultCmp;
}
pos = array.indexOf(item);
if (pos === -1) {
return;
}
_siftdown(array, 0, pos, cmp);
return _siftup(array, pos, cmp);
};
/*
Find the n largest elements in a dataset.
*/
nlargest = function(array, n, cmp) {
var elem, result, _i, _len, _ref;
if (cmp == null) {
cmp = defaultCmp;
}
result = array.slice(0, n);
if (!result.length) {
return result;
}
heapify(result, cmp);
_ref = array.slice(n);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
elem = _ref[_i];
heappushpop(result, elem, cmp);
}
return result.sort(cmp).reverse();
};
/*
Find the n smallest elements in a dataset.
*/
nsmallest = function(array, n, cmp) {
var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;
if (cmp == null) {
cmp = defaultCmp;
}
if (n * 10 <= array.length) {
result = array.slice(0, n).sort(cmp);
if (!result.length) {
return result;
}
los = result[result.length - 1];
_ref = array.slice(n);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
elem = _ref[_i];
if (cmp(elem, los) < 0) {
insort(result, elem, 0, null, cmp);
result.pop();
los = result[result.length - 1];
}
}
return result;
}
heapify(array, cmp);
_results = [];
for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
_results.push(heappop(array, cmp));
}
return _results;
};
_siftdown = function(array, startpos, pos, cmp) {
var newitem, parent, parentpos;
if (cmp == null) {
cmp = defaultCmp;
}
newitem = array[pos];
while (pos > startpos) {
parentpos = (pos - 1) >> 1;
parent = array[parentpos];
if (cmp(newitem, parent) < 0) {
array[pos] = parent;
pos = parentpos;
continue;
}
break;
}
return array[pos] = newitem;
};
_siftup = function(array, pos, cmp) {
var childpos, endpos, newitem, rightpos, startpos;
if (cmp == null) {
cmp = defaultCmp;
}
endpos = array.length;
startpos = pos;
newitem = array[pos];
childpos = 2 * pos + 1;
while (childpos < endpos) {
rightpos = childpos + 1;
if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {
childpos = rightpos;
}
array[pos] = array[childpos];
pos = childpos;
childpos = 2 * pos + 1;
}
array[pos] = newitem;
return _siftdown(array, startpos, pos, cmp);
};
Heap = (function() {
Heap.push = heappush;
Heap.pop = heappop;
Heap.replace = heapreplace;
Heap.pushpop = heappushpop;
Heap.heapify = heapify;
Heap.updateItem = updateItem;
Heap.nlargest = nlargest;
Heap.nsmallest = nsmallest;
function Heap(cmp) {
this.cmp = cmp != null ? cmp : defaultCmp;
this.nodes = [];
}
Heap.prototype.push = function(x) {
return heappush(this.nodes, x, this.cmp);
};
Heap.prototype.pop = function() {
return heappop(this.nodes, this.cmp);
};
Heap.prototype.peek = function() {
return this.nodes[0];
};
Heap.prototype.contains = function(x) {
return this.nodes.indexOf(x) !== -1;
};
Heap.prototype.replace = function(x) {
return heapreplace(this.nodes, x, this.cmp);
};
Heap.prototype.pushpop = function(x) {
return heappushpop(this.nodes, x, this.cmp);
};
Heap.prototype.heapify = function() {
return heapify(this.nodes, this.cmp);
};
Heap.prototype.updateItem = function(x) {
return updateItem(this.nodes, x, this.cmp);
};
Heap.prototype.clear = function() {
return this.nodes = [];
};
Heap.prototype.empty = function() {
return this.nodes.length === 0;
};
Heap.prototype.size = function() {
return this.nodes.length;
};
Heap.prototype.clone = function() {
var heap;
heap = new Heap();
heap.nodes = this.nodes.slice(0);
return heap;
};
Heap.prototype.toArray = function() {
return this.nodes.slice(0);
};
Heap.prototype.insert = Heap.prototype.push;
Heap.prototype.top = Heap.prototype.peek;
Heap.prototype.front = Heap.prototype.peek;
Heap.prototype.has = Heap.prototype.contains;
Heap.prototype.copy = Heap.prototype.clone;
return Heap;
})();
(function(root, factory) {
if (true) {
return !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else if (typeof exports === 'object') {
return module.exports = factory();
} else {
return root.Heap = factory();
}
})(this, function() {
return Heap;
});
}).call(this);
/***/ }),
/* 34 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
// search, spanning trees, etc
var elesfn = {
// kruskal's algorithm (finds min spanning tree, assuming undirected graph)
// implemented from pseudocode from wikipedia
kruskal: function kruskal(weightFn) {
var cy = this.cy();
weightFn = is.fn(weightFn) ? weightFn : function () {
return 1;
}; // if not specified, assume each edge has equal weight (1)
function findSet(ele) {
for (var i = 0; i < forest.length; i++) {
var eles = forest[i];
if (eles.anySame(ele)) {
return {
eles: eles,
index: i
};
}
}
}
var A = cy.collection(cy, []);
var forest = [];
var nodes = this.nodes();
for (var i = 0; i < nodes.length; i++) {
forest.push(nodes[i].collection());
}
var edges = this.edges();
var S = edges.toArray().sort(function (a, b) {
var weightA = weightFn(a);
var weightB = weightFn(b);
return weightA - weightB;
});
for (var i = 0; i < S.length; i++) {
var edge = S[i];
var u = edge.source()[0];
var v = edge.target()[0];
var setU = findSet(u);
var setV = findSet(v);
if (setU.index !== setV.index) {
A = A.add(edge);
// combine forests for u and v
forest[setU.index] = setU.eles.add(setV.eles);
forest.splice(setV.index, 1);
}
}
return nodes.add(A);
}
};
module.exports = elesfn;
/***/ }),
/* 35 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var elesfn = {
// Implemented from pseudocode from wikipedia
aStar: function aStar(options) {
var eles = this;
options = options || {};
// Reconstructs the path from Start to End, acumulating the result in pathAcum
var reconstructPath = function reconstructPath(start, end, cameFromMap, pathAcum) {
// Base case
if (start == end) {
pathAcum.unshift(cy.getElementById(end));
return pathAcum;
}
if (end in cameFromMap) {
// We know which node is before the last one
var previous = cameFromMap[end];
var previousEdge = cameFromEdge[end];
pathAcum.unshift(cy.getElementById(previousEdge));
pathAcum.unshift(cy.getElementById(end));
return reconstructPath(start, previous, cameFromMap, pathAcum);
}
// We should not reach here!
return undefined;
};
// Returns the index of the element in openSet which has minimum fScore
var findMin = function findMin(openSet, fScore) {
if (openSet.length === 0) {
// Should never be the case
return undefined;
}
var minPos = 0;
var tempScore = fScore[openSet[0]];
for (var i = 1; i < openSet.length; i++) {
var s = fScore[openSet[i]];
if (s < tempScore) {
tempScore = s;
minPos = i;
}
}
return minPos;
};
var cy = this._private.cy;
// root - mandatory!
if (options != null && options.root != null) {
var source = is.string(options.root) ?
// use it as a selector, e.g. "#rootID
this.filter(options.root)[0] : options.root[0];
} else {
return undefined;
}
// goal - mandatory!
if (options.goal != null) {
var target = is.string(options.goal) ?
// use it as a selector, e.g. "#goalID
this.filter(options.goal)[0] : options.goal[0];
} else {
return undefined;
}
// Heuristic function - optional
if (options.heuristic != null && is.fn(options.heuristic)) {
var heuristic = options.heuristic;
} else {
var heuristic = function heuristic() {
return 0;
}; // use constant if unspecified
}
// Weight function - optional
if (options.weight != null && is.fn(options.weight)) {
var weightFn = options.weight;
} else {
// If not specified, assume each edge has equal weight (1)
var weightFn = function weightFn(e) {
return 1;
};
}
// directed - optional
if (options.directed != null) {
var directed = options.directed;
} else {
var directed = false;
}
var sid = source.id();
var tid = target.id();
var closedSet = [];
var openSet = [sid];
var cameFrom = {};
var cameFromEdge = {};
var gScore = {};
var fScore = {};
gScore[sid] = 0;
fScore[sid] = heuristic(source);
// Counter
var steps = 0;
// Main loop
while (openSet.length > 0) {
var minPos = findMin(openSet, fScore);
var cMin = cy.getElementById(openSet[minPos]);
var cMinId = cMin.id();
steps++;
// If we've found our goal, then we are done
if (cMinId == tid) {
var rPath = reconstructPath(sid, tid, cameFrom, []);
return {
found: true,
distance: gScore[cMinId],
path: eles.spawn(rPath),
steps: steps
};
}
// Add cMin to processed nodes
closedSet.push(cMinId);
// Remove cMin from boundary nodes
openSet.splice(minPos, 1);
// 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 (closedSet.indexOf(wid) != -1) {
continue;
}
// New tentative score for node w
var tempScore = gScore[cMinId] + weightFn(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 (openSet.indexOf(wid) == -1) {
gScore[wid] = tempScore;
fScore[wid] = tempScore + heuristic(w);
openSet.push(wid); // Add node to openSet
cameFrom[wid] = cMinId;
cameFromEdge[wid] = e.id();
continue;
}
// w already in openSet, but with greater gScore
if (tempScore < gScore[wid]) {
gScore[wid] = tempScore;
fScore[wid] = tempScore + heuristic(w);
cameFrom[wid] = cMinId;
}
} // 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
module.exports = elesfn;
/***/ }),
/* 36 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var elesfn = {
// Implemented from pseudocode from wikipedia
floydWarshall: function floydWarshall(options) {
options = options || {};
var cy = this.cy();
// Weight function - optional
if (options.weight != null && is.fn(options.weight)) {
var weightFn = options.weight;
} else {
// If not specified, assume each edge has equal weight (1)
var weightFn = function weightFn(e) {
return 1;
};
}
// directed - optional
if (options.directed != null) {
var directed = options.directed;
} else {
var directed = false;
}
var edges = this.edges().stdFilter(function (e) {
return !e.isLoop();
});
var nodes = this.nodes();
var numNodes = nodes.length;
// mapping: node id -> position in nodes array
var id2position = {};
for (var i = 0; i < numNodes; i++) {
id2position[nodes[i].id()] = i;
}
// Initialize distance matrix
var dist = [];
for (var i = 0; i < numNodes; i++) {
var newRow = new Array(numNodes);
for (var j = 0; j < numNodes; j++) {
if (i == j) {
newRow[j] = 0;
} else {
newRow[j] = Infinity;
}
}
dist.push(newRow);
}
// Initialize matrix used for path reconstruction
// Initialize distance matrix
var next = [];
var edgeNext = [];
var initMatrix = function initMatrix(next) {
for (var i = 0; i < numNodes; i++) {
var newRow = new Array(numNodes);
for (var j = 0; j < numNodes; j++) {
newRow[j] = undefined;
}
next.push(newRow);
}
};
initMatrix(next);
initMatrix(edgeNext);
// Process edges
for (var i = 0; i < edges.length; i++) {
var sourceIndex = id2position[edges[i].source().id()];
var targetIndex = id2position[edges[i].target().id()];
var weight = weightFn(edges[i]);
// Check if already process another edge between same 2 nodes
if (dist[sourceIndex][targetIndex] > weight) {
dist[sourceIndex][targetIndex] = weight;
next[sourceIndex][targetIndex] = targetIndex;
edgeNext[sourceIndex][targetIndex] = edges[i];
}
}
// If undirected graph, process 'reversed' edges
if (!directed) {
for (var i = 0; i < edges.length; i++) {
var sourceIndex = id2position[edges[i].target().id()];
var targetIndex = id2position[edges[i].source().id()];
var weight = weightFn(edges[i]);
// Check if already process another edge between same 2 nodes
if (dist[sourceIndex][targetIndex] > weight) {
dist[sourceIndex][targetIndex] = weight;
next[sourceIndex][targetIndex] = targetIndex;
edgeNext[sourceIndex][targetIndex] = edges[i];
}
}
}
// Main loop
for (var k = 0; k < numNodes; k++) {
for (var i = 0; i < numNodes; i++) {
for (var j = 0; j < numNodes; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
next[i][j] = next[i][k];
}
}
}
}
// Build result object
var position2id = [];
for (var i = 0; i < numNodes; i++) {
position2id.push(nodes[i].id());
}
var res = {
distance: function distance(from, to) {
if (is.string(from)) {
// from is a selector string
var fromId = cy.filter(from)[0].id();
} else {
// from is a node
var fromId = from.id();
}
if (is.string(to)) {
// to is a selector string
var toId = cy.filter(to)[0].id();
} else {
// to is a node
var toId = to.id();
}
return dist[id2position[fromId]][id2position[toId]];
},
path: function path(from, to) {
var reconstructPathAux = function reconstructPathAux(from, to, next, position2id, edgeNext) {
if (from === to) {
return cy.getElementById(position2id[from]);
}
if (next[from][to] === undefined) {
return undefined;
}
var path = [cy.getElementById(position2id[from])];
var prev = from;
while (from !== to) {
prev = from;
from = next[from][to];
var edge = edgeNext[prev][from];
path.push(edge);
path.push(cy.getElementById(position2id[from]));
}
return path;
};
if (is.string(from)) {
// from is a selector string
var fromId = cy.filter(from)[0].id();
} else {
// from is a node
var fromId = from.id();
}
if (is.string(to)) {
// to is a selector string
var toId = cy.filter(to)[0].id();
} else {
// to is a node
var toId = to.id();
}
var pathArr = reconstructPathAux(id2position[fromId], id2position[toId], next, position2id, edgeNext);
return cy.collection(pathArr);
}
};
return res;
} // floydWarshall
}; // elesfn
module.exports = elesfn;
/***/ }),
/* 37 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var elesfn = {
// Implemented from pseudocode from wikipedia
bellmanFord: function bellmanFord(options) {
var eles = this;
options = options || {};
// Weight function - optional
if (options.weight != null && is.fn(options.weight)) {
var weightFn = options.weight;
} else {
// If not specified, assume each edge has equal weight (1)
var weightFn = function weightFn(e) {
return 1;
};
}
// directed - optional
if (options.directed != null) {
var directed = options.directed;
} else {
var directed = false;
}
// root - mandatory!
if (options.root != null) {
if (is.string(options.root)) {
// use it as a selector, e.g. "#rootID
var source = this.filter(options.root)[0];
} else {
var source = options.root[0];
}
} else {
return undefined;
}
var cy = this._private.cy;
var edges = this.edges().stdFilter(function (e) {
return !e.isLoop();
});
var nodes = this.nodes();
var numNodes = nodes.length;
// mapping: node id -> position in nodes array
var id2position = {};
for (var i = 0; i < numNodes; i++) {
id2position[nodes[i].id()] = i;
}
// Initializations
var cost = [];
var predecessor = [];
var predEdge = [];
for (var i = 0; i < numNodes; i++) {
if (nodes[i].id() === source.id()) {
cost[i] = 0;
} else {
cost[i] = Infinity;
}
predecessor[i] = undefined;
}
// Edges relaxation
var flag = false;
for (var i = 1; i < numNodes; i++) {
flag = false;
for (var e = 0; e < edges.length; e++) {
var sourceIndex = id2position[edges[e].source().id()];
var targetIndex = id2position[edges[e].target().id()];
var weight = weightFn(edges[e]);
var temp = cost[sourceIndex] + weight;
if (temp < cost[targetIndex]) {
cost[targetIndex] = temp;
predecessor[targetIndex] = sourceIndex;
predEdge[targetIndex] = edges[e];
flag = true;
}
// If undirected graph, we need to take into account the 'reverse' edge
if (!directed) {
var temp = cost[targetIndex] + weight;
if (temp < cost[sourceIndex]) {
cost[sourceIndex] = temp;
predecessor[sourceIndex] = targetIndex;
predEdge[sourceIndex] = edges[e];
flag = true;
}
}
}
if (!flag) {
break;
}
}
if (flag) {
// Check for negative weight cycles
for (var e = 0; e < edges.length; e++) {
var sourceIndex = id2position[edges[e].source().id()];
var targetIndex = id2position[edges[e].target().id()];
var weight = weightFn(edges[e]);
if (cost[sourceIndex] + weight < cost[targetIndex]) {
util.error('Graph contains a negative weight cycle for Bellman-Ford');
return { pathTo: undefined,
distanceTo: undefined,
hasNegativeWeightCycle: true };
}
}
}
// Build result object
var position2id = [];
for (var i = 0; i < numNodes; i++) {
position2id.push(nodes[i].id());
}
var res = {
distanceTo: function distanceTo(to) {
if (is.string(to)) {
// to is a selector string
var toId = cy.filter(to)[0].id();
} else {
// to is a node
var toId = to.id();
}
return cost[id2position[toId]];
},
pathTo: function pathTo(to) {
var reconstructPathAux = function reconstructPathAux(predecessor, fromPos, toPos, position2id, acumPath, predEdge) {
for (;;) {
// Add toId to path
acumPath.push(cy.getElementById(position2id[toPos]));
acumPath.push(predEdge[toPos]);
if (fromPos === toPos) {
// reached starting node
return acumPath;
}
// If no path exists, discart acumulated path and return undefined
var predPos = predecessor[toPos];
if (typeof predPos === 'undefined') {
return undefined;
}
toPos = predPos;
}
};
if (is.string(to)) {
// to is a selector string
var toId = cy.filter(to)[0].id();
} else {
// to is a node
var toId = to.id();
}
var path = [];
// This returns a reversed path
var res = reconstructPathAux(predecessor, id2position[source.id()], id2position[toId], position2id, path, predEdge);
// Get it in the correct order and return it
if (res != null) {
res.reverse();
}
return eles.spawn(res);
},
hasNegativeWeightCycle: false
};
return res;
} // bellmanFord
}; // elesfn
module.exports = elesfn;
/***/ }),
/* 38 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var elesfn = {
// Computes the minimum cut of an undirected graph
// Returns the correct answer with high probability
kargerStein: function kargerStein(options) {
var eles = this;
options = options || {};
// Function which colapses 2 (meta) nodes into one
// Updates the remaining edge lists
// Receives as a paramater the edge which causes the collapse
var colapse = function colapse(edgeIndex, nodeMap, remainingEdges) {
var edgeInfo = remainingEdges[edgeIndex];
var sourceIn = edgeInfo[1];
var targetIn = edgeInfo[2];
var partition1 = nodeMap[sourceIn];
var partition2 = nodeMap[targetIn];
// Delete all edges between partition1 and partition2
var newEdges = remainingEdges.filter(function (edge) {
if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) {
return false;
}
if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) {
return false;
}
return true;
});
// All edges pointing to partition2 should now point to partition1
for (var i = 0; i < newEdges.length; i++) {
var edge = newEdges[i];
if (edge[1] === partition2) {
// Check source
newEdges[i] = edge.slice(0);
newEdges[i][1] = partition1;
} else if (edge[2] === partition2) {
// Check target
newEdges[i] = edge.slice(0);
newEdges[i][2] = partition1;
}
}
// Move all nodes from partition2 to partition1
for (var i = 0; i < nodeMap.length; i++) {
if (nodeMap[i] === partition2) {
nodeMap[i] = partition1;
}
}
return newEdges;
};
// Contracts a graph until we reach a certain number of meta nodes
var contractUntil = function contractUntil(metaNodeMap, remainingEdges, size, sizeLimit) {
// Stop condition
if (size <= sizeLimit) {
return remainingEdges;
}
// Choose an edge randomly
var edgeIndex = Math.floor(Math.random() * remainingEdges.length);
// Colapse graph based on edge
var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges);
return contractUntil(metaNodeMap, newEdges, size - 1, sizeLimit);
};
var cy = this._private.cy;
var edges = this.edges().stdFilter(function (e) {
return !e.isLoop();
});
var nodes = this.nodes();
var numNodes = nodes.length;
var numEdges = edges.length;
var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));
var stopSize = Math.floor(numNodes / Math.sqrt(2));
if (numNodes < 2) {
util.error('At least 2 nodes are required for Karger-Stein algorithm');
return undefined;
}
// Create numerical identifiers for each node
// mapping: node id -> position in nodes array
// for reverse mapping, simply use nodes array
var id2position = {};
for (var i = 0; i < numNodes; i++) {
id2position[nodes[i].id()] = i;
}
// Now store edge destination as indexes
// Format for each edge (edge index, source node index, target node index)
var edgeIndexes = [];
for (var i = 0; i < numEdges; i++) {
var e = edges[i];
edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]);
}
// We will store the best cut found here
var minCutSize = Infinity;
var minCut;
// Initial meta node partition
var originalMetaNode = [];
for (var i = 0; i < numNodes; i++) {
originalMetaNode.push(i);
}
// Main loop
for (var iter = 0; iter <= numIter; iter++) {
// Create new meta node partition
var metaNodeMap = originalMetaNode.slice(0);
// Contract until stop point (stopSize nodes)
var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize);
// Create a copy of the colapsed nodes state
var metaNodeMap2 = metaNodeMap.slice(0);
// Run 2 iterations starting in the stop state
var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);
var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2);
// Is any of the 2 results the best cut so far?
if (res1.length <= res2.length && res1.length < minCutSize) {
minCutSize = res1.length;
minCut = [res1, metaNodeMap];
} else if (res2.length <= res1.length && res2.length < minCutSize) {
minCutSize = res2.length;
minCut = [res2, metaNodeMap2];
}
} // end of main loop
// Construct result
var resEdges = minCut[0].map(function (e) {
return edges[e[0]];
});
var partition1 = [];
var partition2 = [];
// traverse metaNodeMap for best cut
var witnessNodePartition = minCut[1][0];
for (var i = 0; i < minCut[1].length; i++) {
var partitionId = minCut[1][i];
if (partitionId === witnessNodePartition) {
partition1.push(nodes[i]);
} else {
partition2.push(nodes[i]);
}
}
var ret = {
cut: eles.spawn(cy, resEdges),
partition1: eles.spawn(partition1),
partition2: eles.spawn(partition2)
};
return ret;
}
}; // elesfn
module.exports = elesfn;
/***/ }),
/* 39 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var elesfn = {
pageRank: function pageRank(options) {
options = options || {};
var normalizeVector = function normalizeVector(vector) {
var length = vector.length;
// First, get sum of all elements
var total = 0;
for (var i = 0; i < length; i++) {
total += vector[i];
}
// Now, divide each by the sum of all elements
for (var i = 0; i < length; i++) {
vector[i] = vector[i] / total;
}
};
// dampingFactor - optional
if (options != null && options.dampingFactor != null) {
var dampingFactor = options.dampingFactor;
} else {
var dampingFactor = 0.8; // Default damping factor
}
// desired precision - optional
if (options != null && options.precision != null) {
var epsilon = options.precision;
} else {
var epsilon = 0.000001; // Default precision
}
// Max number of iterations - optional
if (options != null && options.iterations != null) {
var numIter = options.iterations;
} else {
var numIter = 200; // Default number of iterations
}
// Weight function - optional
if (options != null && options.weight != null && is.fn(options.weight)) {
var weightFn = options.weight;
} else {
// If not specified, assume each edge has equal weight (1)
var weightFn = function weightFn(e) {
return 1;
};
}
var cy = this._private.cy;
var edges = this.edges().stdFilter(function (e) {
return !e.isLoop();
});
var nodes = this.nodes();
var numNodes = nodes.length;
var numEdges = edges.length;
// Create numerical identifiers for each node
// mapping: node id -> position in nodes array
// for reverse mapping, simply use nodes array
var id2position = {};
for (var i = 0; i < numNodes; i++) {
id2position[nodes[i].id()] = i;
}
// Construct transposed adjacency matrix
// First lets have a zeroed matrix of the right size
// We'll also keep track of the sum of each column
var matrix = [];
var columnSum = [];
var additionalProb = (1 - dampingFactor) / numNodes;
// Create null matric
for (var i = 0; i < numNodes; i++) {
var newRow = [];
for (var j = 0; j < numNodes; j++) {
newRow.push(0.0);
}
matrix.push(newRow);
columnSum.push(0.0);
}
// Now, process edges
for (var i = 0; i < numEdges; i++) {
var edge = edges[i];
var s = id2position[edge.source().id()];
var t = id2position[edge.target().id()];
var w = weightFn(edge);
// Update matrix
matrix[t][s] += w;
// Update column sum
columnSum[s] += w;
}
// Add additional probability based on damping factor
// Also, take into account columns that have sum = 0
var p = 1.0 / numNodes + additionalProb; // Shorthand
// Traverse matrix, column by column
for (var j = 0; j < numNodes; j++) {
if (columnSum[j] === 0) {
// No 'links' out from node jth, assume equal probability for each possible node
for (var i = 0; i < numNodes; i++) {
matrix[i][j] = p;
}
} else {
// Node jth has outgoing link, compute normalized probabilities
for (var i = 0; i < numNodes; i++) {
matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb;
}
}
}
// Compute dominant eigenvector using power method
var eigenvector = [];
var nullVector = [];
var previous;
// Start with a vector of all 1's
// Also, initialize a null vector which will be used as shorthand
for (var i = 0; i < numNodes; i++) {
eigenvector.push(1.0);
nullVector.push(0.0);
}
for (var iter = 0; iter < numIter; iter++) {
// New array with all 0's
var temp = nullVector.slice(0);
// Multiply matrix with previous result
for (var i = 0; i < numNodes; i++) {
for (var j = 0; j < numNodes; j++) {
temp[i] += matrix[i][j] * eigenvector[j];
}
}
normalizeVector(temp);
previous = eigenvector;
eigenvector = temp;
var diff = 0;
// Compute difference (squared module) of both vectors
for (var i = 0; i < numNodes; i++) {
diff += Math.pow(previous[i] - eigenvector[i], 2);
}
// If difference is less than the desired threshold, stop iterating
if (diff < epsilon) {
break;
}
}
// Construct result
var res = {
rank: function rank(node) {
if (is.string(node)) {
// is a selector string
var nodeId = cy.filter(node)[0].id();
} else {
// is a node object
var nodeId = node.id();
}
return eigenvector[id2position[nodeId]];
}
};
return res;
} // pageRank
}; // elesfn
module.exports = elesfn;
/***/ }),
/* 40 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var elesfn = {
degreeCentralityNormalized: function degreeCentralityNormalized(options) {
options = options || {};
var cy = this.cy();
// directed - optional
if (options.directed != null) {
var directed = options.directed;
} else {
var directed = false;
}
var nodes = this.nodes();
var numNodes = nodes.length;
if (!directed) {
var degrees = {};
var maxDegree = 0;
for (var i = 0; i < numNodes; i++) {
var node = nodes[i];
// add current node to the current options object and call degreeCentrality
var currDegree = this.degreeCentrality(util.extend({}, options, { root: node }));
if (maxDegree < currDegree.degree) maxDegree = currDegree.degree;
degrees[node.id()] = currDegree.degree;
}
return {
degree: function degree(node) {
if (maxDegree == 0) return 0;
if (is.string(node)) {
// from is a selector string
var node = cy.filter(node)[0].id();
} else {
// from is a node
var node = node.id();
}
return degrees[node] / maxDegree;
}
};
} else {
var indegrees = {};
var outdegrees = {};
var maxIndegree = 0;
var maxOutdegree = 0;
for (var i = 0; i < numNodes; i++) {
var node = nodes[i];
// add current node to the current options object and call degreeCentrality
var currDegree = this.degreeCentrality(util.extend({}, options, { root: node }));
if (maxIndegree < currDegree.indegree) maxIndegree = currDegree.indegree;
if (maxOutdegree < currDegree.outdegree) maxOutdegree = currDegree.outdegree;
indegrees[node.id()] = currDegree.indegree;
outdegrees[node.id()] = currDegree.outdegree;
}
return {
indegree: function indegree(node) {
if (maxIndegree == 0) return 0;
if (is.string(node)) {
// from is a selector string
var node = cy.filter(node)[0].id();
} else {
// from is a node
var node = node.id();
}
return indegrees[node] / maxIndegree;
},
outdegree: function outdegree(node) {
if (maxOutdegree == 0) return 0;
if (is.string(node)) {
// from is a selector string
var node = cy.filter(node)[0].id();
} else {
// from is a node
var node = node.id();
}
return outdegrees[node] / maxOutdegree;
}
};
}
}, // degreeCentralityNormalized
// Implemented from the algorithm in Opsahl's paper
// "Node centrality in weighted networks: Generalizing degree and shortest paths"
// check the heading 2 "Degree"
degreeCentrality: function degreeCentrality(options) {
options = options || {};
var callingEles = this;
// root - mandatory!
if (options != null && options.root != null) {
var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0];
} else {
return undefined;
}
// weight - optional
if (options.weight != null && is.fn(options.weight)) {
var weightFn = options.weight;
} else {
// If not specified, assume each edge has equal weight (1)
var weightFn = function weightFn(e) {
return 1;
};
}
// directed - optional
if (options.directed != null) {
var directed = options.directed;
} else {
var directed = false;
}
// alpha - optional
if (options.alpha != null && is.number(options.alpha)) {
var alpha = options.alpha;
} else {
alpha = 0;
}
if (!directed) {
var connEdges = root.connectedEdges().intersection(callingEles);
var k = connEdges.length;
var s = 0;
// Now, sum edge weights
for (var i = 0; i < connEdges.length; i++) {
var edge = connEdges[i];
s += weightFn(edge);
}
return {
degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)
};
} else {
var incoming = root.connectedEdges('edge[target = "' + root.id() + '"]').intersection(callingEles);
var outgoing = root.connectedEdges('edge[source = "' + root.id() + '"]').intersection(callingEles);
var k_in = incoming.length;
var k_out = outgoing.length;
var s_in = 0;
var s_out = 0;
// Now, sum incoming edge weights
for (var i = 0; i < incoming.length; i++) {
var edge = incoming[i];
s_in += weightFn(edge);
}
// Now, sum outgoing edge weights
for (var i = 0; i < outgoing.length; i++) {
var edge = outgoing[i];
s_out += weightFn(edge);
}
return {
indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),
outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)
};
}
} // degreeCentrality
}; // elesfn
// nice, short mathemathical alias
elesfn.dc = elesfn.degreeCentrality;
elesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized;
module.exports = elesfn;
/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var elesfn = {
closenessCentralityNormalized: function closenessCentralityNormalized(options) {
options = options || {};
var cy = this.cy();
var harmonic = options.harmonic;
if (harmonic === undefined) {
harmonic = true;
}
var closenesses = {};
var maxCloseness = 0;
var nodes = this.nodes();
var fw = this.floydWarshall({ weight: options.weight, directed: options.directed });
// Compute closeness for every node and find the maximum closeness
for (var i = 0; i < nodes.length; i++) {
var currCloseness = 0;
for (var j = 0; j < nodes.length; j++) {
if (i != j) {
var d = fw.distance(nodes[i], nodes[j]);
if (harmonic) {
currCloseness += 1 / d;
} else {
currCloseness += d;
}
}
}
if (!harmonic) {
currCloseness = 1 / currCloseness;
}
if (maxCloseness < currCloseness) {
maxCloseness = currCloseness;
}
closenesses[nodes[i].id()] = currCloseness;
}
return {
closeness: function closeness(node) {
if (maxCloseness == 0) {
return 0;
}
if (is.string(node)) {
// from is a selector string
var node = cy.filter(node)[0].id();
} else {
// from is a node
var node = node.id();
}
return closenesses[node] / maxCloseness;
}
};
},
// Implemented from pseudocode from wikipedia
closenessCentrality: function closenessCentrality(options) {
options = options || {};
// root - mandatory!
if (options.root != null) {
if (is.string(options.root)) {
// use it as a selector, e.g. "#rootID
var root = this.filter(options.root)[0];
} else {
var root = options.root[0];
}
} else {
return undefined;
}
// weight - optional
if (options.weight != null && is.fn(options.weight)) {
var weight = options.weight;
} else {
var weight = function weight() {
return 1;
};
}
// directed - optional
if (options.directed != null && is.bool(options.directed)) {
var directed = options.directed;
} else {
var directed = false;
}
var harmonic = options.harmonic;
if (harmonic === undefined) {
harmonic = true;
}
// we need distance from this node to every other node
var dijkstra = this.dijkstra({
root: root,
weight: weight,
directed: directed
});
var totalDistance = 0;
var nodes = this.nodes();
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].id() != root.id()) {
var d = dijkstra.distanceTo(nodes[i]);
if (harmonic) {
totalDistance += 1 / d;
} else {
totalDistance += d;
}
}
}
return harmonic ? totalDistance : 1 / totalDistance;
} // closenessCentrality
}; // elesfn
// nice, short mathemathical alias
elesfn.cc = elesfn.closenessCentrality;
elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized;
module.exports = elesfn;
/***/ }),
/* 42 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Heap = __webpack_require__(9);
var elesfn = {
// Implemented from the algorithm in the paper "On Variants of Shortest-Path Betweenness Centrality and their Generic Computation" by Ulrik Brandes
betweennessCentrality: function betweennessCentrality(options) {
options = options || {};
// Weight - optional
var weighted, weightFn;
if (is.fn(options.weight)) {
weightFn = options.weight;
weighted = true;
} else {
weighted = false;
}
// Directed - default false
var directed = options.directed != null ? options.directed : false;
var cy = this._private.cy;
// starting
var V = this.nodes();
var A = {};
var _C = {};
var max = 0;
var C = {
set: function set(key, val) {
_C[key] = val;
if (val > max) {
max = val;
}
},
get: function get(key) {
return _C[key];
}
};
// A contains the neighborhoods of every node
for (var i = 0; i < V.length; i++) {
var v = V[i];
var vid = v.id();
if (directed) {
A[vid] = v.outgoers().nodes(); // get outgoers of every node
} else {
A[vid] = v.openNeighborhood().nodes(); // get neighbors of every node
}
C.set(vid, 0);
}
for (var s = 0; s < V.length; s++) {
var sid = V[s].id();
var S = []; // stack
var P = {};
var g = {};
var d = {};
var Q = new Heap(function (a, b) {
return d[a] - d[b];
}); // queue
// init dictionaries
for (var i = 0; i < V.length; i++) {
var vid = V[i].id();
P[vid] = [];
g[vid] = 0;
d[vid] = Infinity;
}
g[sid] = 1; // sigma
d[sid] = 0; // distance to s
Q.push(sid);
while (!Q.empty()) {
var v = Q.pop();
S.push(v);
if (weighted) {
for (var j = 0; j < A[v].length; j++) {
var w = A[v][j];
var vEle = cy.getElementById(v);
var edge;
if (vEle.edgesTo(w).length > 0) {
edge = vEle.edgesTo(w)[0];
} else {
edge = w.edgesTo(vEle)[0];
}
var edgeWeight = weightFn(edge);
w = w.id();
if (d[w] > d[v] + edgeWeight) {
d[w] = d[v] + edgeWeight;
if (Q.nodes.indexOf(w) < 0) {
//if w is not in Q
Q.push(w);
} else {
// update position if w is in Q
Q.updateItem(w);
}
g[w] = 0;
P[w] = [];
}
if (d[w] == d[v] + edgeWeight) {
g[w] = g[w] + g[v];
P[w].push(v);
}
}
} else {
for (var j = 0; j < A[v].length; j++) {
var w = A[v][j].id();
if (d[w] == Infinity) {
Q.push(w);
d[w] = d[v] + 1;
}
if (d[w] == d[v] + 1) {
g[w] = g[w] + g[v];
P[w].push(v);
}
}
}
}
var e = {};
for (var i = 0; i < V.length; i++) {
e[V[i].id()] = 0;
}
while (S.length > 0) {
var w = S.pop();
for (var j = 0; j < P[w].length; j++) {
var v = P[w][j];
e[v] = e[v] + g[v] / g[w] * (1 + e[w]);
if (w != V[s].id()) {
C.set(w, C.get(w) + e[w]);
}
}
}
}
var ret = {
betweenness: function betweenness(node) {
if (is.string(node)) {
var node = cy.filter(node).id();
} else {
var node = node.id();
}
return C.get(node);
},
betweennessNormalized: function betweennessNormalized(node) {
if (max == 0) return 0;
if (is.string(node)) {
var node = cy.filter(node).id();
} else {
var node = node.id();
}
return C.get(node) / max;
}
};
// alias
ret.betweennessNormalised = ret.betweennessNormalized;
return ret;
} // betweennessCentrality
}; // elesfn
// nice, short mathemathical alias
elesfn.bc = elesfn.betweennessCentrality;
module.exports = elesfn;
/***/ }),
/* 43 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var define = __webpack_require__(4);
var elesfn = {
animate: define.animate(),
animation: define.animation(),
animated: define.animated(),
clearQueue: define.clearQueue(),
delay: define.delay(),
delayAnimation: define.delayAnimation(),
stop: define.stop()
};
module.exports = elesfn;
/***/ }),
/* 44 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var Animation = __webpack_require__(45);
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var define = {
animated: function animated() {
return function animatedImpl() {
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return false;
}
var ele = all[0];
if (ele) {
return ele._private.animation.current.length > 0;
}
};
}, // animated
clearQueue: function clearQueue() {
return function clearQueueImpl() {
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return this;
}
for (var i = 0; i < all.length; i++) {
var ele = all[i];
ele._private.animation.queue = [];
}
return this;
};
}, // clearQueue
delay: function delay() {
return function delayImpl(time, complete) {
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return this;
}
return this.animate({
delay: time,
duration: time,
complete: complete
});
};
}, // delay
delayAnimation: function delayAnimation() {
return function delayAnimationImpl(time, complete) {
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return this;
}
return this.animation({
delay: time,
duration: time,
complete: complete
});
};
}, // delay
animation: function animation() {
return function animationImpl(properties, params) {
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var cy = this._private.cy || this;
var isCore = !selfIsArrayLike;
var isEles = !isCore;
if (!cy.styleEnabled()) {
return this;
}
var style = cy.style();
properties = util.assign({}, properties, params);
var propertiesEmpty = Object.keys(properties).length === 0;
if (propertiesEmpty) {
return new Animation(all[0], properties); // nothing to animate
}
if (properties.duration === undefined) {
properties.duration = 400;
}
switch (properties.duration) {
case 'slow':
properties.duration = 600;
break;
case 'fast':
properties.duration = 200;
break;
}
if (isEles) {
properties.style = style.getPropsList(properties.style || properties.css);
properties.css = undefined;
}
if (isEles && properties.renderedPosition != null) {
var rpos = properties.renderedPosition;
var pan = cy.pan();
var zoom = cy.zoom();
properties.position = math.renderedToModelPosition(rpos, zoom, pan);
}
// override pan w/ panBy if set
if (isCore && properties.panBy != null) {
var panBy = properties.panBy;
var cyPan = cy.pan();
properties.pan = {
x: cyPan.x + panBy.x,
y: cyPan.y + panBy.y
};
}
// override pan w/ center if set
var center = properties.center || properties.centre;
if (isCore && center != null) {
var centerPan = cy.getCenterPan(center.eles, properties.zoom);
if (centerPan != null) {
properties.pan = centerPan;
}
}
// override pan & zoom w/ fit if set
if (isCore && properties.fit != null) {
var fit = properties.fit;
var fitVp = cy.getFitViewport(fit.eles || fit.boundingBox, fit.padding);
if (fitVp != null) {
properties.pan = fitVp.pan;
properties.zoom = fitVp.zoom;
}
}
// override zoom (& potentially pan) w/ zoom obj if set
if (isCore && is.plainObject(properties.zoom)) {
var vp = cy.getZoomedViewport(properties.zoom);
if (vp != null) {
if (vp.zoomed) {
properties.zoom = vp.zoom;
}
if (vp.panned) {
properties.pan = vp.pan;
}
}
}
return new Animation(all[0], properties);
};
}, // animate
animate: function animate() {
return function animateImpl(properties, params) {
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return this;
}
if (params) {
properties = util.extend({}, properties, params);
}
// manually hook and run the animation
for (var i = 0; i < all.length; i++) {
var ele = all[i];
var queue = ele.animated() && (properties.queue === undefined || properties.queue);
var ani = ele.animation(properties, queue ? { queue: true } : undefined);
ani.play();
}
return this; // chaining
};
}, // animate
stop: function stop() {
return function stopImpl(clearQueue, jumpToEnd) {
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var cy = this._private.cy || this;
if (!cy.styleEnabled()) {
return this;
}
for (var i = 0; i < all.length; i++) {
var ele = all[i];
var _p = ele._private;
var anis = _p.animation.current;
for (var j = 0; j < anis.length; j++) {
var ani = anis[j];
var ani_p = ani._private;
if (jumpToEnd) {
// next iteration of the animation loop, the animation
// will go straight to the end and be removed
ani_p.duration = 0;
}
}
// clear the queue of future animations
if (clearQueue) {
_p.animation.queue = [];
}
if (!jumpToEnd) {
_p.animation.current = [];
}
}
// we have to notify (the animation loop doesn't do it for us on `stop`)
cy.notify({
eles: this,
type: 'draw'
});
return this;
};
} // stop
}; // define
module.exports = define;
/***/ }),
/* 45 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var Promise = __webpack_require__(5);
var Animation = function Animation(target, opts, opts2) {
var _p = this._private = util.extend({
duration: 1000
}, opts, opts2);
_p.target = target;
_p.style = _p.style || _p.css;
_p.started = false;
_p.playing = false;
_p.hooked = false;
_p.applying = false;
_p.progress = 0;
_p.completes = [];
_p.frames = [];
if (_p.complete && is.fn(_p.complete)) {
_p.completes.push(_p.complete);
}
// for future timeline/animations impl
this.length = 1;
this[0] = this;
};
var anifn = Animation.prototype;
util.extend(anifn, {
instanceString: function instanceString() {
return 'animation';
},
hook: function hook() {
var _p = this._private;
if (!_p.hooked) {
// add to target's animation queue
var q = void 0;
var tAni = _p.target._private.animation;
if (_p.queue) {
q = tAni.queue;
} else {
q = tAni.current;
}
q.push(this);
// add to the animation loop pool
if (is.elementOrCollection(_p.target)) {
_p.target.cy().addToAnimationPool(_p.target);
}
_p.hooked = true;
}
return this;
},
play: function play() {
var _p = this._private;
// autorewind
if (_p.progress === 1) {
_p.progress = 0;
}
_p.playing = true;
_p.started = false; // needs to be started by animation loop
_p.stopped = false;
this.hook();
// the animation loop will start the animation...
return this;
},
playing: function playing() {
return this._private.playing;
},
apply: function apply() {
var _p = this._private;
_p.applying = true;
_p.started = false; // needs to be started by animation loop
_p.stopped = false;
this.hook();
// the animation loop will apply the animation at this progress
return this;
},
applying: function applying() {
return this._private.applying;
},
pause: function pause() {
var _p = this._private;
_p.playing = false;
_p.started = false;
return this;
},
stop: function stop() {
var _p = this._private;
_p.playing = false;
_p.started = false;
_p.stopped = true; // to be removed from animation queues
return this;
},
rewind: function rewind() {
return this.progress(0);
},
fastforward: function fastforward() {
return this.progress(1);
},
time: function time(t) {
var _p = this._private;
if (t === undefined) {
return _p.progress * _p.duration;
} else {
return this.progress(t / _p.duration);
}
},
progress: function progress(p) {
var _p = this._private;
var wasPlaying = _p.playing;
if (p === undefined) {
return _p.progress;
} else {
if (wasPlaying) {
this.pause();
}
_p.progress = p;
_p.started = false;
if (wasPlaying) {
this.play();
}
}
return this;
},
completed: function completed() {
return this._private.progress === 1;
},
reverse: function reverse() {
var _p = this._private;
var wasPlaying = _p.playing;
if (wasPlaying) {
this.pause();
}
_p.progress = 1 - _p.progress;
_p.started = false;
var swap = function swap(a, b) {
var _pa = _p[a];
if (_pa == null) {
return;
}
_p[a] = _p[b];
_p[b] = _pa;
};
swap('zoom', 'startZoom');
swap('pan', 'startPan');
swap('position', 'startPosition');
// swap styles
if (_p.style) {
for (var i = 0; i < _p.style.length; i++) {
var prop = _p.style[i];
var name = prop.name;
var startStyleProp = _p.startStyle[name];
_p.startStyle[name] = prop;
_p.style[i] = startStyleProp;
}
}
if (wasPlaying) {
this.play();
}
return this;
},
promise: function promise(type) {
var _p = this._private;
var arr = void 0;
switch (type) {
case 'frame':
arr = _p.frames;
break;
default:
case 'complete':
case 'completed':
arr = _p.completes;
}
return new Promise(function (resolve, reject) {
arr.push(function () {
resolve();
});
});
}
});
anifn.complete = anifn.completed;
module.exports = Animation;
/***/ }),
/* 46 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
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; }
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var define = {
// access data field
data: function data(params) {
var defaults = {
field: 'data',
bindingEvent: 'data',
allowBinding: false,
allowSetting: false,
allowGetting: false,
settingEvent: 'data',
settingTriggersEvent: false,
triggerFnName: 'trigger',
immutableKeys: {}, // key => true if immutable
updateStyle: false,
beforeGet: function beforeGet(self) {},
beforeSet: function beforeSet(self, obj) {},
onSet: function onSet(self) {},
canSet: function canSet(self) {
return true;
}
};
params = util.extend({}, defaults, params);
return function dataImpl(name, value) {
var p = params;
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
var single = selfIsArrayLike ? self[0] : self;
// .data('foo', ...)
if (is.string(name)) {
// set or get property
// .data('foo')
if (p.allowGetting && value === undefined) {
// get
var ret = void 0;
if (single) {
p.beforeGet(single);
ret = single._private[p.field][name];
}
return ret;
// .data('foo', 'bar')
} else if (p.allowSetting && value !== undefined) {
// set
var valid = !p.immutableKeys[name];
if (valid) {
var change = _defineProperty({}, name, value);
p.beforeSet(self, change);
for (var i = 0, l = all.length; i < l; i++) {
var ele = all[i];
if (p.canSet(ele)) {
ele._private[p.field][name] = value;
}
}
// update mappers if asked
if (p.updateStyle) {
self.updateStyle();
}
// call onSet callback
p.onSet(self);
if (p.settingTriggersEvent) {
self[p.triggerFnName](p.settingEvent);
}
}
}
// .data({ 'foo': 'bar' })
} else if (p.allowSetting && is.plainObject(name)) {
// extend
var obj = name;
var k = void 0,
v = void 0;
var keys = Object.keys(obj);
p.beforeSet(self, obj);
for (var _i = 0; _i < keys.length; _i++) {
k = keys[_i];
v = obj[k];
var _valid = !p.immutableKeys[k];
if (_valid) {
for (var j = 0; j < all.length; j++) {
var _ele = all[j];
if (p.canSet(_ele)) {
_ele._private[p.field][k] = v;
}
}
}
}
// update mappers if asked
if (p.updateStyle) {
self.updateStyle();
}
// call onSet callback
p.onSet(self);
if (p.settingTriggersEvent) {
self[p.triggerFnName](p.settingEvent);
}
// .data(function(){ ... })
} else if (p.allowBinding && is.fn(name)) {
// bind to event
var fn = name;
self.on(p.bindingEvent, fn);
// .data()
} else if (p.allowGetting && name === undefined) {
// get whole object
var _ret = void 0;
if (single) {
p.beforeGet(single);
_ret = single._private[p.field];
}
return _ret;
}
return self; // maintain chainability
}; // function
}, // data
// remove data field
removeData: function removeData(params) {
var defaults = {
field: 'data',
event: 'data',
triggerFnName: 'trigger',
triggerEvent: false,
immutableKeys: {} // key => true if immutable
};
params = util.extend({}, defaults, params);
return function removeDataImpl(names) {
var p = params;
var self = this;
var selfIsArrayLike = self.length !== undefined;
var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
// .removeData('foo bar')
if (is.string(names)) {
// then get the list of keys, and delete them
var keys = names.split(/\s+/);
var l = keys.length;
for (var i = 0; i < l; i++) {
// delete each non-empty key
var key = keys[i];
if (is.emptyString(key)) {
continue;
}
var valid = !p.immutableKeys[key]; // not valid if immutable
if (valid) {
for (var i_a = 0, l_a = all.length; i_a < l_a; i_a++) {
all[i_a]._private[p.field][key] = undefined;
}
}
}
if (p.triggerEvent) {
self[p.triggerFnName](p.event);
}
// .removeData()
} else if (names === undefined) {
// then delete all keys
for (var _i_a = 0, _l_a = all.length; _i_a < _l_a; _i_a++) {
var _privateFields = all[_i_a]._private[p.field];
var _keys = Object.keys(_privateFields);
for (var _i2 = 0; _i2 < _keys.length; _i2++) {
var _key = _keys[_i2];
var validKeyToDelete = !p.immutableKeys[_key];
if (validKeyToDelete) {
_privateFields[_key] = undefined;
}
}
}
if (p.triggerEvent) {
self[p.triggerFnName](p.event);
}
}
return self; // maintain chaining
}; // function
} // removeData
}; // define
module.exports = define;
/***/ }),
/* 47 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Promise = __webpack_require__(5);
var define = {
eventAliasesOn: function eventAliasesOn(proto) {
var p = proto;
p.addListener = p.listen = p.bind = p.on;
p.unlisten = p.unbind = p.off = p.removeListener;
p.trigger = p.emit;
// this is just a wrapper alias of .on()
p.pon = p.promiseOn = function (events, selector) {
var self = this;
var args = Array.prototype.slice.call(arguments, 0);
return new Promise(function (resolve, reject) {
var callback = function callback(e) {
self.off.apply(self, offArgs);
resolve(e);
};
var onArgs = args.concat([callback]);
var offArgs = onArgs.concat([]);
self.on.apply(self, onArgs);
});
};
}
}; // define
module.exports = define;
/***/ }),
/* 48 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Set = __webpack_require__(8);
var elesfn = {
classes: function classes(_classes) {
_classes = (_classes || '').match(/\S+/g) || [];
var self = this;
var changed = [];
var classesMap = new Set(_classes);
// check and update each ele
var _loop = function _loop(j) {
var ele = self[j];
var _p = ele._private;
var eleClasses = _p.classes;
var changedEle = false;
// check if ele has all of the passed classes
classesMap.forEach(function (cls) {
var eleHasClass = eleClasses.has(cls);
if (!eleHasClass) {
changedEle = true;
}
});
// check if ele has classes outside of those passed
if (!changedEle) {
eleClasses.forEach(function (eleCls) {
var specdClass = classesMap.has(eleCls);
if (!specdClass) {
changedEle = true;
}
});
}
if (changedEle) {
_p.classes = new Set(classesMap);
changed.push(ele);
}
};
for (var j = 0; j < self.length; j++) {
_loop(j);
}
// trigger update style on those eles that had class changes
if (changed.length > 0) {
this.spawn(changed).updateStyle().emit('class');
}
return self;
},
addClass: function addClass(classes) {
return this.toggleClass(classes, true);
},
hasClass: function hasClass(className) {
var ele = this[0];
return ele != null && ele._private.classes.has(className);
},
toggleClass: function toggleClass(classesStr, toggle) {
var classes = classesStr.match(/\S+/g) || [];
var self = this;
var changed = []; // eles who had classes changed
for (var i = 0, il = self.length; i < il; i++) {
var _ele = self[i];
var _changedEle = false;
for (var j = 0; j < classes.length; j++) {
var cls = classes[j];
var _eleClasses = _ele._private.classes;
var hasClass = _eleClasses.has(cls);
var shouldAdd = toggle || toggle === undefined && !hasClass;
if (shouldAdd) {
_eleClasses.add(cls);
if (!hasClass && !_changedEle) {
changed.push(_ele);
_changedEle = true;
}
} else {
// then remove
_eleClasses.delete(cls);
if (hasClass && !_changedEle) {
changed.push(_ele);
_changedEle = true;
}
}
} // for j classes
} // for i eles
// trigger update style on those eles that had class changes
if (changed.length > 0) {
this.spawn(changed).updateStyle().emit('class');
}
return self;
},
removeClass: function removeClass(classes) {
return this.toggleClass(classes, false);
},
flashClass: function flashClass(classes, duration) {
var self = this;
if (duration == null) {
duration = 250;
} else if (duration === 0) {
return self; // nothing to do really
}
self.addClass(classes);
setTimeout(function () {
self.removeClass(classes);
}, duration);
return self;
}
};
module.exports = elesfn;
/***/ }),
/* 49 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Selector = __webpack_require__(6);
var elesfn = {
allAre: function allAre(selector) {
var selObj = new Selector(selector);
return this.every(function (ele) {
return selObj.matches(ele);
});
},
is: function is(selector) {
var selObj = new Selector(selector);
return this.some(function (ele) {
return selObj.matches(ele);
});
},
some: function some(fn, thisArg) {
for (var i = 0; i < this.length; i++) {
var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]);
if (ret) {
return true;
}
}
return false;
},
every: function every(fn, thisArg) {
for (var i = 0; i < this.length; i++) {
var ret = !thisArg ? fn(this[i], i, this) : fn.apply(thisArg, [this[i], i, this]);
if (!ret) {
return false;
}
}
return true;
},
same: function same(collection) {
collection = this.cy().collection(collection);
// cheap extra check
if (this.length !== collection.length) {
return false;
}
return this.every(function (ele) {
return collection.hasElementWithId(ele.id());
});
},
anySame: function anySame(collection) {
collection = this.cy().collection(collection);
return this.some(function (ele) {
return collection.hasElementWithId(ele.id());
});
},
allAreNeighbors: function allAreNeighbors(collection) {
collection = this.cy().collection(collection);
var nhood = this.neighborhood();
return collection.every(function (ele) {
return nhood.hasElementWithId(ele.id());
});
},
contains: function contains(collection) {
collection = this.cy().collection(collection);
var self = this;
return collection.every(function (ele) {
return self.hasElementWithId(ele.id());
});
}
};
elesfn.allAreNeighbours = elesfn.allAreNeighbors;
elesfn.has = elesfn.contains;
module.exports = elesfn;
/***/ }),
/* 50 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var exprs = __webpack_require__(51);
var newQuery = __webpack_require__(10);
// of all the expressions, find the first match in the remaining text
var consumeExpr = function consumeExpr(remaining) {
var expr = void 0;
var match = void 0;
var name = void 0;
for (var j = 0; j < exprs.length; j++) {
var e = exprs[j];
var n = e.name;
var m = remaining.match(e.regexObj);
if (m != null) {
match = m;
expr = e;
name = n;
var consumed = m[0];
remaining = remaining.substring(consumed.length);
break; // we've consumed one expr, so we can return now
}
}
return {
expr: expr,
match: match,
name: name,
remaining: remaining
};
};
// consume all leading whitespace
var consumeWhitespace = function consumeWhitespace(remaining) {
var match = remaining.match(/^\s+/);
if (match) {
var consumed = match[0];
remaining = remaining.substring(consumed.length);
}
return remaining;
};
var parse = function parse(selector) {
var self = this;
var remaining = self._private.selectorText = selector;
var currentQuery = self[0] = newQuery();
self.length = 1;
remaining = consumeWhitespace(remaining); // get rid of leading whitespace
for (;;) {
var check = consumeExpr(remaining);
if (check.expr == null) {
util.error('The selector `' + selector + '`is invalid');
return false;
} else {
var args = check.match.slice(1);
// let the token populate the selector object in currentQuery
var ret = check.expr.populate(self, currentQuery, args);
if (ret === false) {
return false; // exit if population failed
} else if (ret != null) {
currentQuery = ret; // change the current query to be filled if the expr specifies
}
}
remaining = check.remaining;
// we're done when there's nothing left to parse
if (remaining.match(/^\s*$/)) {
break;
}
}
// adjust references for subject
for (var j = 0; j < self.length; j++) {
var query = self[j];
if (query.subject != null) {
// go up the tree until we reach the subject
for (;;) {
if (query.subject === query) {
break;
} // done if subject is self
if (query.parent != null) {
// swap parent/child reference
var parent = query.parent;
var child = query;
child.parent = null;
parent.child = child;
query = parent; // go up the tree
} else if (query.ancestor != null) {
// swap ancestor/descendant
var ancestor = query.ancestor;
var descendant = query;
descendant.ancestor = null;
ancestor.descendant = descendant;
query = ancestor; // go up the tree
} else if (query.source || query.target || query.connectedNodes) {
util.error('The selector `' + self.text() + '` can not contain a subject selector that applies to the source or target of an edge selector');
return false;
} else {
util.error('When adjusting references for the selector `' + self.text() + '`, neither parent nor ancestor was found');
return false;
}
} // for
self[j] = query.subject; // subject should be the root query
} // if
} // for
return true; // success
};
module.exports = { parse: parse };
/***/ }),
/* 51 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _require = __webpack_require__(15),
stateSelectorRegex = _require.stateSelectorRegex;
var tokens = __webpack_require__(52);
var util = __webpack_require__(1);
var newQuery = __webpack_require__(10);
// when a token like a variable has escaped meta characters, we need to clean the backslashes out
// so that values get compared properly in Selector.filter()
var cleanMetaChars = function cleanMetaChars(str) {
return str.replace(new RegExp('\\\\(' + tokens.metaChar + ')', 'g'), function (match, $1) {
return $1;
});
};
var replaceLastQuery = function replaceLastQuery(selector, examiningQuery, replacementQuery) {
if (examiningQuery === selector[selector.length - 1]) {
selector[selector.length - 1] = replacementQuery;
}
};
// NOTE: add new expression syntax here to have it recognised by the parser;
// - a query contains all adjacent (i.e. no separator in between) expressions;
// - the current query is stored in selector[i] --- you can use the reference to `this` in the populate function;
// - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward
// - when you add something here, also add to Selector.toString()
var exprs = [{
name: 'group',
query: true,
regex: '(' + tokens.group + ')',
populate: function populate(selector, query, _ref) {
var _ref2 = _slicedToArray(_ref, 1),
group = _ref2[0];
query.group = group === '*' ? group : group + 's';
}
}, {
name: 'state',
query: true,
regex: stateSelectorRegex,
populate: function populate(selector, query, _ref3) {
var _ref4 = _slicedToArray(_ref3, 1),
state = _ref4[0];
query.colonSelectors.push(state);
}
}, {
name: 'id',
query: true,
regex: '\\#(' + tokens.id + ')',
populate: function populate(selector, query, _ref5) {
var _ref6 = _slicedToArray(_ref5, 1),
id = _ref6[0];
query.ids.push(cleanMetaChars(id));
}
}, {
name: 'className',
query: true,
regex: '\\.(' + tokens.className + ')',
populate: function populate(selector, query, _ref7) {
var _ref8 = _slicedToArray(_ref7, 1),
className = _ref8[0];
query.classes.push(cleanMetaChars(className));
}
}, {
name: 'dataExists',
query: true,
regex: '\\[\\s*(' + tokens.variable + ')\\s*\\]',
populate: function populate(selector, query, _ref9) {
var _ref10 = _slicedToArray(_ref9, 1),
variable = _ref10[0];
query.data.push({
field: cleanMetaChars(variable)
});
}
}, {
name: 'dataCompare',
query: true,
regex: '\\[\\s*(' + tokens.variable + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.value + ')\\s*\\]',
populate: function populate(selector, query, _ref11) {
var _ref12 = _slicedToArray(_ref11, 3),
variable = _ref12[0],
comparatorOp = _ref12[1],
value = _ref12[2];
var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;
if (valueIsString) {
value = value.substring(1, value.length - 1);
} else {
value = parseFloat(value);
}
query.data.push({
field: cleanMetaChars(variable),
operator: comparatorOp,
value: value
});
}
}, {
name: 'dataBool',
query: true,
regex: '\\[\\s*(' + tokens.boolOp + ')\\s*(' + tokens.variable + ')\\s*\\]',
populate: function populate(selector, query, _ref13) {
var _ref14 = _slicedToArray(_ref13, 2),
boolOp = _ref14[0],
variable = _ref14[1];
query.data.push({
field: cleanMetaChars(variable),
operator: boolOp
});
}
}, {
name: 'metaCompare',
query: true,
regex: '\\[\\[\\s*(' + tokens.meta + ')\\s*(' + tokens.comparatorOp + ')\\s*(' + tokens.number + ')\\s*\\]\\]',
populate: function populate(selector, query, _ref15) {
var _ref16 = _slicedToArray(_ref15, 3),
meta = _ref16[0],
comparatorOp = _ref16[1],
number = _ref16[2];
query.meta.push({
field: cleanMetaChars(meta),
operator: comparatorOp,
value: parseFloat(number)
});
}
}, {
name: 'nextQuery',
separator: true,
regex: tokens.separator,
populate: function populate(selector) {
// go on to next query
var nextQuery = selector[selector.length++] = newQuery();
selector.currentSubject = null;
return nextQuery;
}
}, {
name: 'directedEdge',
separator: true,
regex: tokens.directedEdge,
populate: function populate(selector, query) {
var edgeQuery = newQuery();
var source = query;
var target = newQuery();
edgeQuery.group = 'edges';
edgeQuery.target = target;
edgeQuery.source = source;
edgeQuery.subject = selector.currentSubject;
// the query in the selector should be the edge rather than the source
replaceLastQuery(selector, query, edgeQuery);
// we're now populating the target query with expressions that follow
return target;
}
}, {
name: 'undirectedEdge',
separator: true,
regex: tokens.undirectedEdge,
populate: function populate(selector, query) {
var edgeQuery = newQuery();
var source = query;
var target = newQuery();
edgeQuery.group = 'edges';
edgeQuery.connectedNodes = [source, target];
edgeQuery.subject = selector.currentSubject;
// the query in the selector should be the edge rather than the source
replaceLastQuery(selector, query, edgeQuery);
// we're now populating the target query with expressions that follow
return target;
}
}, {
name: 'child',
separator: true,
regex: tokens.child,
populate: function populate(selector, query) {
// this query is the parent of the following query
var childQuery = newQuery();
childQuery.parent = query;
childQuery.subject = selector.currentSubject;
// it's cheaper to compare children first and go up so replace the parent
replaceLastQuery(selector, query, childQuery);
// we're now populating the child query with expressions that follow
return childQuery;
}
}, {
name: 'descendant',
separator: true,
regex: tokens.descendant,
populate: function populate(selector, query) {
// this query is the ancestor of the following query
var descendantQuery = newQuery();
descendantQuery.ancestor = query;
descendantQuery.subject = selector.currentSubject;
// it's cheaper to compare descendants first and go up so replace the ancestor
replaceLastQuery(selector, query, descendantQuery);
// we're now populating the descendant query with expressions that follow
return descendantQuery;
}
}, {
name: 'subject',
modifier: true,
regex: tokens.subject,
populate: function populate(selector, query) {
if (selector.currentSubject != null && query.subject != query) {
util.error('Redefinition of subject in selector `' + selector.toString() + '`');
return false;
}
selector.currentSubject = query;
query.subject = query;
selector[selector.length - 1].subject = query;
}
}];
exprs.forEach(function (e) {
return e.regexObj = new RegExp('^' + e.regex);
});
module.exports = exprs;
/***/ }),
/* 52 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
// tokens in the query language
var tokens = {
metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in let names, etc
comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors)
boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors)
string: '"(?:\\\\"|[^"])*"' + '|' + "'(?:\\\\'|[^'])*'", // string literals (used in data selectors) -- doublequotes | singlequotes
number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123
meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection)
separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass
descendant: '\\s+',
child: '\\s+>\\s+',
subject: '\\$',
group: 'node|edge|\\*',
directedEdge: '\\s+->\\s+',
undirectedEdge: '\\s+<->\\s+'
};
tokens.variable = '(?:[\\w-]|(?:\\\\' + tokens.metaChar + '))+'; // a variable name
tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number
tokens.className = tokens.variable; // a class name (follows variable conventions)
tokens.id = tokens.variable; // an element id (follows variable conventions)
(function () {
var ops = void 0,
op = void 0,
i = void 0;
// add @ variants to comparatorOp
ops = tokens.comparatorOp.split('|');
for (i = 0; i < ops.length; i++) {
op = ops[i];
tokens.comparatorOp += '|@' + op;
}
// add ! variants to comparatorOp
ops = tokens.comparatorOp.split('|');
for (i = 0; i < ops.length; i++) {
op = ops[i];
if (op.indexOf('!') >= 0) {
continue;
} // skip ops that explicitly contain !
if (op === '=') {
continue;
} // skip = b/c != is explicitly defined
tokens.comparatorOp += '|\\!' + op;
}
})();
module.exports = tokens;
/***/ }),
/* 53 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _require = __webpack_require__(15),
stateSelectorMatches = _require.stateSelectorMatches;
var is = __webpack_require__(0);
// generic checking for data/metadata
var operandsMatch = function operandsMatch(query, params) {
var allDataMatches = true;
for (var k = 0; k < query[params.name].length; k++) {
var data = query[params.name][k];
var operator = data.operator;
var value = data.value;
var field = data.field;
var _matches = void 0;
var fieldVal = params.fieldValue(field);
if (operator != null && value != null) {
var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal;
var valStr = '' + value;
var caseInsensitive = false;
if (operator.indexOf('@') >= 0) {
fieldStr = fieldStr.toLowerCase();
valStr = valStr.toLowerCase();
operator = operator.replace('@', '');
caseInsensitive = true;
}
var notExpr = false;
if (operator.indexOf('!') >= 0) {
operator = operator.replace('!', '');
notExpr = true;
}
// if we're doing a case insensitive comparison, then we're using a STRING comparison
// even if we're comparing numbers
if (caseInsensitive) {
value = valStr.toLowerCase();
fieldVal = fieldStr.toLowerCase();
}
var isIneqCmp = false;
switch (operator) {
case '*=':
_matches = fieldStr.indexOf(valStr) >= 0;
break;
case '$=':
_matches = fieldStr.indexOf(valStr, fieldStr.length - valStr.length) >= 0;
break;
case '^=':
_matches = fieldStr.indexOf(valStr) === 0;
break;
case '=':
_matches = fieldVal === value;
break;
case '>':
isIneqCmp = true;
_matches = fieldVal > value;
break;
case '>=':
isIneqCmp = true;
_matches = fieldVal >= value;
break;
case '<':
isIneqCmp = true;
_matches = fieldVal < value;
break;
case '<=':
isIneqCmp = true;
_matches = fieldVal <= value;
break;
default:
_matches = false;
break;
}
// apply the not op, but null vals for inequalities should always stay non-matching
if (notExpr && (fieldVal != null || !isIneqCmp)) {
_matches = !_matches;
}
} else if (operator != null) {
switch (operator) {
case '?':
_matches = fieldVal ? true : false;
break;
case '!':
_matches = fieldVal ? false : true;
break;
case '^':
_matches = fieldVal === undefined;
break;
}
} else {
_matches = fieldVal !== undefined;
}
if (!_matches) {
allDataMatches = false;
break;
}
} // for
return allDataMatches;
}; // operandsMatch
// check parent/child relations
var confirmRelations = function confirmRelations(query, isNecessary, eles) {
if (query != null) {
var _matches2 = false;
if (!isNecessary) {
return false;
}
eles = eles(); // save cycles if query == null
// query must match for at least one element (may be recursive)
for (var i = 0; i < eles.length; i++) {
if (queryMatches(query, eles[i])) {
_matches2 = true;
break;
}
}
return _matches2;
} else {
return true;
}
};
var queryMatches = function queryMatches(query, ele) {
// make single group-only selectors really cheap to check since they're the most common ones
if (query.groupOnly) {
return query.group === '*' || query.group === ele.group();
}
// check group
if (query.group != null && query.group != '*' && query.group != ele.group()) {
return false;
}
var cy = ele.cy();
var k = void 0;
// check colon selectors
var allColonSelectorsMatch = true;
for (k = 0; k < query.colonSelectors.length; k++) {
var sel = query.colonSelectors[k];
allColonSelectorsMatch = stateSelectorMatches(sel, ele);
if (!allColonSelectorsMatch) break;
}
if (!allColonSelectorsMatch) return false;
// check id
var allIdsMatch = true;
for (k = 0; k < query.ids.length; k++) {
var id = query.ids[k];
var actualId = ele.id();
allIdsMatch = allIdsMatch && id == actualId;
if (!allIdsMatch) break;
}
if (!allIdsMatch) return false;
// check classes
var allClassesMatch = true;
for (k = 0; k < query.classes.length; k++) {
var cls = query.classes[k];
allClassesMatch = allClassesMatch && ele.hasClass(cls);
if (!allClassesMatch) break;
}
if (!allClassesMatch) return false;
// check data matches
var allDataMatches = operandsMatch(query, {
name: 'data',
fieldValue: function fieldValue(field) {
return ele.data(field);
}
});
if (!allDataMatches) {
return false;
}
// check metadata matches
var allMetaMatches = operandsMatch(query, {
name: 'meta',
fieldValue: function fieldValue(field) {
return ele[field]();
}
});
if (!allMetaMatches) {
return false;
}
// check collection
if (query.collection != null) {
var matchesAny = query.collection.hasElementWithId(ele.id());
if (!matchesAny) {
return false;
}
}
// check filter function
if (query.filter != null && ele.collection().some(query.filter)) {
return false;
}
var isCompound = cy.hasCompoundNodes();
var getSource = function getSource() {
return ele.source();
};
var getTarget = function getTarget() {
return ele.target();
};
if (!confirmRelations(query.parent, isCompound, function () {
return ele.parent();
})) {
return false;
}
if (!confirmRelations(query.ancestor, isCompound, function () {
return ele.parents();
})) {
return false;
}
if (!confirmRelations(query.child, isCompound, function () {
return ele.children();
})) {
return false;
}
if (!confirmRelations(query.descendant, isCompound, function () {
return ele.descendants();
})) {
return false;
}
if (!confirmRelations(query.source, true, getSource)) {
return false;
}
if (!confirmRelations(query.target, true, getTarget)) {
return false;
}
if (query.connectedNodes) {
var q0 = query.connectedNodes[0];
var q1 = query.connectedNodes[1];
if (confirmRelations(q0, true, getSource) && confirmRelations(q1, true, getTarget)) {
// match
} else if (confirmRelations(q0, true, getTarget) && confirmRelations(q1, true, getSource)) {
// match
} else {
return false;
}
}
// we've reached the end, so we've matched everything for this query
return true;
}; // queryMatches
// filter an existing collection
var filter = function filter(collection) {
var self = this;
var cy = collection.cy();
// don't bother trying if it's invalid
if (self.invalid()) {
return cy.collection();
}
// for 1 id #foo queries, just get the element
if (self.length === 1 && self[0].length === 1 && self[0].ids.length === 1) {
return collection.getElementById(self[0].ids[0]).collection();
}
var selectorFunction = function selectorFunction(element) {
for (var j = 0; j < self.length; j++) {
var query = self[j];
if (queryMatches(query, element)) {
return true;
}
}
return false;
};
if (self.text() == null) {
selectorFunction = function selectorFunction() {
return true;
};
}
var filteredCollection = collection.filter(selectorFunction);
return filteredCollection;
}; // filter
// does selector match a single element?
var matches = function matches(ele) {
var self = this;
// don't bother trying if it's invalid
if (self.invalid()) {
return false;
}
for (var j = 0; j < self.length; j++) {
var query = self[j];
if (queryMatches(query, ele)) {
return true;
}
}
return false;
}; // filter
module.exports = { matches: matches, filter: filter };
/***/ }),
/* 54 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Set = __webpack_require__(8);
var elesfn = {
parent: function parent(selector) {
var parents = [];
// optimisation for single ele call
if (this.length === 1) {
var parent = this[0]._private.parent;
if (parent) {
return parent;
}
}
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var _parent = ele._private.parent;
if (_parent) {
parents.push(_parent);
}
}
return this.spawn(parents, { unique: true }).filter(selector);
},
parents: function parents(selector) {
var parents = [];
var eles = this.parent();
while (eles.nonempty()) {
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
parents.push(ele);
}
eles = eles.parent();
}
return this.spawn(parents, { unique: true }).filter(selector);
},
commonAncestors: function commonAncestors(selector) {
var ancestors = void 0;
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var parents = ele.parents();
ancestors = ancestors || parents;
ancestors = ancestors.intersect(parents); // current list must be common with current ele parents set
}
return ancestors.filter(selector);
},
orphans: function orphans(selector) {
return this.stdFilter(function (ele) {
return ele.isOrphan();
}).filter(selector);
},
nonorphans: function nonorphans(selector) {
return this.stdFilter(function (ele) {
return ele.isChild();
}).filter(selector);
},
children: function children(selector) {
var children = [];
for (var i = 0; i < this.length; i++) {
var ele = this[i];
children = children.concat(ele._private.children);
}
return this.spawn(children, { unique: true }).filter(selector);
},
siblings: function siblings(selector) {
return this.parent().children().not(this).filter(selector);
},
isParent: function isParent() {
var ele = this[0];
if (ele) {
return ele.isNode() && ele._private.children.length !== 0;
}
},
isChildless: function isChildless() {
var ele = this[0];
if (ele) {
return ele.isNode() && ele._private.children.length === 0;
}
},
isChild: function isChild() {
var ele = this[0];
if (ele) {
return ele.isNode() && ele._private.parent != null;
}
},
isOrphan: function isOrphan() {
var ele = this[0];
if (ele) {
return ele.isNode() && ele._private.parent == null;
}
},
descendants: function descendants(selector) {
var elements = [];
function add(eles) {
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
elements.push(ele);
if (ele.children().nonempty()) {
add(ele.children());
}
}
}
add(this.children());
return this.spawn(elements, { unique: true }).filter(selector);
}
};
function forEachCompound(eles, fn, includeSelf, recursiveStep) {
var q = [];
var did = new Set();
var cy = eles.cy();
var hasCompounds = cy.hasCompoundNodes();
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (includeSelf) {
q.push(ele);
} else if (hasCompounds) {
recursiveStep(q, did, ele);
}
}
while (q.length > 0) {
var _ele = q.shift();
fn(_ele);
did.add(_ele.id());
if (hasCompounds) {
recursiveStep(q, did, _ele);
}
}
return eles;
}
function addChildren(q, did, ele) {
if (ele.isParent()) {
var children = ele._private.children;
for (var i = 0; i < children.length; i++) {
var child = children[i];
if (!did.has(child.id())) {
q.push(child);
}
}
}
}
// very efficient version of eles.add( eles.descendants() ).forEach()
// for internal use
elesfn.forEachDown = function (fn) {
var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
return forEachCompound(this, fn, includeSelf, addChildren);
};
function addParent(q, did, ele) {
if (ele.isChild()) {
var parent = ele._private.parent;
if (!did.has(parent.id())) {
q.push(parent);
}
}
}
elesfn.forEachUp = function (fn) {
var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
return forEachCompound(this, fn, includeSelf, addParent);
};
function addParentAndChildren(q, did, ele) {
addParent(q, did, ele);
addChildren(q, did, ele);
}
elesfn.forEachUpAndDown = function (fn) {
var includeSelf = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
return forEachCompound(this, fn, includeSelf, addParentAndChildren);
};
// aliases
elesfn.ancestors = elesfn.parents;
module.exports = elesfn;
/***/ }),
/* 55 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var define = __webpack_require__(4);
var fn = void 0,
elesfn = void 0;
fn = elesfn = {
data: define.data({
field: 'data',
bindingEvent: 'data',
allowBinding: true,
allowSetting: true,
settingEvent: 'data',
settingTriggersEvent: true,
triggerFnName: 'trigger',
allowGetting: true,
immutableKeys: {
'id': true,
'source': true,
'target': true,
'parent': true
},
updateStyle: true
}),
removeData: define.removeData({
field: 'data',
event: 'data',
triggerFnName: 'trigger',
triggerEvent: true,
immutableKeys: {
'id': true,
'source': true,
'target': true,
'parent': true
},
updateStyle: true
}),
scratch: define.data({
field: 'scratch',
bindingEvent: 'scratch',
allowBinding: true,
allowSetting: true,
settingEvent: 'scratch',
settingTriggersEvent: true,
triggerFnName: 'trigger',
allowGetting: true,
updateStyle: true
}),
removeScratch: define.removeData({
field: 'scratch',
event: 'scratch',
triggerFnName: 'trigger',
triggerEvent: true,
updateStyle: true
}),
rscratch: define.data({
field: 'rscratch',
allowBinding: false,
allowSetting: true,
settingTriggersEvent: false,
allowGetting: true
}),
removeRscratch: define.removeData({
field: 'rscratch',
triggerEvent: false
}),
id: function id() {
var ele = this[0];
if (ele) {
return ele._private.data.id;
}
}
};
// aliases
fn.attr = fn.data;
fn.removeAttr = fn.removeData;
module.exports = elesfn;
/***/ }),
/* 56 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var elesfn = {};
function defineDegreeFunction(callback) {
return function (includeLoops) {
var self = this;
if (includeLoops === undefined) {
includeLoops = true;
}
if (self.length === 0) {
return;
}
if (self.isNode() && !self.removed()) {
var degree = 0;
var node = self[0];
var connectedEdges = node._private.edges;
for (var i = 0; i < connectedEdges.length; i++) {
var edge = connectedEdges[i];
if (!includeLoops && edge.isLoop()) {
continue;
}
degree += callback(node, edge);
}
return degree;
} else {
return;
}
};
}
util.extend(elesfn, {
degree: defineDegreeFunction(function (node, edge) {
if (edge.source().same(edge.target())) {
return 2;
} else {
return 1;
}
}),
indegree: defineDegreeFunction(function (node, edge) {
if (edge.target().same(node)) {
return 1;
} else {
return 0;
}
}),
outdegree: defineDegreeFunction(function (node, edge) {
if (edge.source().same(node)) {
return 1;
} else {
return 0;
}
})
});
function defineDegreeBoundsFunction(degreeFn, callback) {
return function (includeLoops) {
var ret = void 0;
var nodes = this.nodes();
for (var i = 0; i < nodes.length; i++) {
var ele = nodes[i];
var degree = ele[degreeFn](includeLoops);
if (degree !== undefined && (ret === undefined || callback(degree, ret))) {
ret = degree;
}
}
return ret;
};
}
util.extend(elesfn, {
minDegree: defineDegreeBoundsFunction('degree', function (degree, min) {
return degree < min;
}),
maxDegree: defineDegreeBoundsFunction('degree', function (degree, max) {
return degree > max;
}),
minIndegree: defineDegreeBoundsFunction('indegree', function (degree, min) {
return degree < min;
}),
maxIndegree: defineDegreeBoundsFunction('indegree', function (degree, max) {
return degree > max;
}),
minOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, min) {
return degree < min;
}),
maxOutdegree: defineDegreeBoundsFunction('outdegree', function (degree, max) {
return degree > max;
})
});
util.extend(elesfn, {
totalDegree: function totalDegree(includeLoops) {
var total = 0;
var nodes = this.nodes();
for (var i = 0; i < nodes.length; i++) {
total += nodes[i].degree(includeLoops);
}
return total;
}
});
module.exports = elesfn;
/***/ }),
/* 57 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var position = __webpack_require__(58);
var bounds = __webpack_require__(59);
var widthHeight = __webpack_require__(60);
var edgePoints = __webpack_require__(61);
module.exports = util.assign({}, position, bounds, widthHeight, edgePoints);
/***/ }),
/* 58 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var define = __webpack_require__(4);
var is = __webpack_require__(0);
var math = __webpack_require__(2);
var fn = void 0,
elesfn = void 0;
var beforePositionSet = function beforePositionSet(eles, newPos) {
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (ele.isParent() && !ele.locked()) {
var oldPos = ele._private.position;
var delta = {
x: newPos.x - oldPos.x,
y: newPos.y - oldPos.y
};
eles.children().shift(delta);
}
}
};
fn = elesfn = {
position: define.data({
field: 'position',
bindingEvent: 'position',
allowBinding: true,
allowSetting: true,
settingEvent: 'position',
settingTriggersEvent: true,
triggerFnName: 'emitAndNotify',
allowGetting: true,
validKeys: ['x', 'y'],
beforeGet: function beforeGet(ele) {
ele.updateCompoundBounds();
},
beforeSet: beforePositionSet,
onSet: function onSet(eles) {
eles.dirtyCompoundBoundsCache();
},
canSet: function canSet(ele) {
return !ele.locked();
}
}),
// position but no notification to renderer
silentPosition: define.data({
field: 'position',
bindingEvent: 'position',
allowBinding: false,
allowSetting: true,
settingEvent: 'position',
settingTriggersEvent: false,
triggerFnName: 'trigger',
allowGetting: false,
validKeys: ['x', 'y'],
beforeSet: beforePositionSet,
onSet: function onSet(eles) {
eles.dirtyCompoundBoundsCache();
},
canSet: function canSet(ele) {
return !ele.locked();
}
}),
positions: function positions(pos, silent) {
if (is.plainObject(pos)) {
if (silent) {
this.silentPosition(pos);
} else {
this.position(pos);
}
} else if (is.fn(pos)) {
var _fn = pos;
var cy = this.cy();
cy.startBatch();
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var _pos = void 0;
if (_pos = _fn(ele, i)) {
if (silent) {
ele.silentPosition(_pos);
} else {
ele.position(_pos);
}
}
}
cy.endBatch();
}
return this; // chaining
},
silentPositions: function silentPositions(pos) {
return this.positions(pos, true);
},
shift: function shift(dim, val) {
var delta = void 0;
if (is.plainObject(dim)) {
delta = dim;
} else if (is.string(dim) && is.number(val)) {
delta = { x: 0, y: 0 };
delta[dim] = val;
}
if (delta != null) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var pos = ele.position();
ele.position({
x: pos.x + delta.x,
y: pos.y + delta.y
});
}
}
return this;
},
// get/set the rendered (i.e. on screen) positon of the element
renderedPosition: function renderedPosition(dim, val) {
var ele = this[0];
var cy = this.cy();
var zoom = cy.zoom();
var pan = cy.pan();
var rpos = is.plainObject(dim) ? dim : undefined;
var setting = rpos !== undefined || val !== undefined && is.string(dim);
if (ele && ele.isNode()) {
// must have an element and must be a node to return position
if (setting) {
for (var i = 0; i < this.length; i++) {
var _ele = this[i];
if (val !== undefined) {
// set one dimension
_ele.position(dim, (val - pan[dim]) / zoom);
} else if (rpos !== undefined) {
// set whole position
_ele.position(math.renderedToModelPosition(rpos, zoom, pan));
}
}
} else {
// getting
var pos = ele.position();
rpos = math.modelToRenderedPosition(pos, zoom, pan);
if (dim === undefined) {
// then return the whole rendered position
return rpos;
} else {
// then return the specified dimension
return rpos[dim];
}
}
} else if (!setting) {
return undefined; // for empty collection case
}
return this; // chaining
},
// get/set the position relative to the parent
relativePosition: function relativePosition(dim, val) {
var ele = this[0];
var cy = this.cy();
var ppos = is.plainObject(dim) ? dim : undefined;
var setting = ppos !== undefined || val !== undefined && is.string(dim);
var hasCompoundNodes = cy.hasCompoundNodes();
if (ele && ele.isNode()) {
// must have an element and must be a node to return position
if (setting) {
for (var i = 0; i < this.length; i++) {
var _ele2 = this[i];
var parent = hasCompoundNodes ? _ele2.parent() : null;
var hasParent = parent && parent.length > 0;
var relativeToParent = hasParent;
if (hasParent) {
parent = parent[0];
}
var origin = relativeToParent ? parent.position() : { x: 0, y: 0 };
if (val !== undefined) {
// set one dimension
_ele2.position(dim, val + origin[dim]);
} else if (ppos !== undefined) {
// set whole position
_ele2.position({
x: ppos.x + origin.x,
y: ppos.y + origin.y
});
}
}
} else {
// getting
var pos = ele.position();
var _parent = hasCompoundNodes ? ele.parent() : null;
var _hasParent = _parent && _parent.length > 0;
var _relativeToParent = _hasParent;
if (_hasParent) {
_parent = _parent[0];
}
var _origin = _relativeToParent ? _parent.position() : { x: 0, y: 0 };
ppos = {
x: pos.x - _origin.x,
y: pos.y - _origin.y
};
if (dim === undefined) {
// then return the whole rendered position
return ppos;
} else {
// then return the specified dimension
return ppos[dim];
}
}
} else if (!setting) {
return undefined; // for empty collection case
}
return this; // chaining
}
};
// aliases
fn.modelPosition = fn.point = fn.position;
fn.modelPositions = fn.points = fn.positions;
fn.renderedPoint = fn.renderedPosition;
fn.relativePoint = fn.relativePosition;
module.exports = elesfn;
/***/ }),
/* 59 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var fn = void 0,
elesfn = void 0;
fn = elesfn = {};
elesfn.renderedBoundingBox = function (options) {
var bb = this.boundingBox(options);
var cy = this.cy();
var zoom = cy.zoom();
var pan = cy.pan();
var x1 = bb.x1 * zoom + pan.x;
var x2 = bb.x2 * zoom + pan.x;
var y1 = bb.y1 * zoom + pan.y;
var y2 = bb.y2 * zoom + pan.y;
return {
x1: x1,
x2: x2,
y1: y1,
y2: y2,
w: x2 - x1,
h: y2 - y1
};
};
elesfn.dirtyCompoundBoundsCache = function () {
var cy = this.cy();
if (!cy.styleEnabled() || !cy.hasCompoundNodes()) {
return this;
}
this.forEachUp(function (ele) {
ele._private.compoundBoundsClean = false;
if (ele.isParent()) {
ele.emit('bounds');
}
});
return this;
};
elesfn.updateCompoundBounds = function () {
var cy = this.cy();
// save cycles for non compound graphs or when style disabled
if (!cy.styleEnabled() || !cy.hasCompoundNodes()) {
return this;
}
// save cycles when batching -- but bounds will be stale (or not exist yet)
if (cy.batching()) {
return this;
}
var updated = [];
function update(parent) {
if (!parent.isParent()) {
return;
}
var _p = parent._private;
var children = parent.children();
var includeLabels = parent.pstyle('compound-sizing-wrt-labels').value === 'include';
var min = {
width: {
val: parent.pstyle('min-width').pfValue,
left: parent.pstyle('min-width-bias-left'),
right: parent.pstyle('min-width-bias-right')
},
height: {
val: parent.pstyle('min-height').pfValue,
top: parent.pstyle('min-height-bias-top'),
bottom: parent.pstyle('min-height-bias-bottom')
}
};
var bb = children.boundingBox({
includeLabels: includeLabels,
includeOverlays: false,
// updating the compound bounds happens outside of the regular
// cache cycle (i.e. before fired events)
useCache: false
});
var pos = _p.position;
// if children take up zero area then keep position and fall back on stylesheet w/h
if (bb.w === 0 || bb.h === 0) {
bb = {
w: parent.pstyle('width').pfValue,
h: parent.pstyle('height').pfValue
};
bb.x1 = pos.x - bb.w / 2;
bb.x2 = pos.x + bb.w / 2;
bb.y1 = pos.y - bb.h / 2;
bb.y2 = pos.y + bb.h / 2;
}
function computeBiasValues(propDiff, propBias, propBiasComplement) {
var biasDiff = 0;
var biasComplementDiff = 0;
var biasTotal = propBias + propBiasComplement;
if (propDiff > 0 && biasTotal > 0) {
biasDiff = propBias / biasTotal * propDiff;
biasComplementDiff = propBiasComplement / biasTotal * propDiff;
}
return {
biasDiff: biasDiff,
biasComplementDiff: biasComplementDiff
};
}
function computePaddingValues(width, height, paddingObject, relativeTo) {
// Assuming percentage is number from 0 to 1
if (paddingObject.units === '%') {
switch (relativeTo) {
case 'width':
return width > 0 ? paddingObject.pfValue * width : 0;
case 'height':
return height > 0 ? paddingObject.pfValue * height : 0;
case 'average':
return width > 0 && height > 0 ? paddingObject.pfValue * (width + height) / 2 : 0;
case 'min':
return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * height : paddingObject.pfValue * width : 0;
case 'max':
return width > 0 && height > 0 ? width > height ? paddingObject.pfValue * width : paddingObject.pfValue * height : 0;
default:
return 0;
}
} else if (paddingObject.units === 'px') {
return paddingObject.pfValue;
} else {
return 0;
}
}
var leftVal = min.width.left.value;
if (min.width.left.units === 'px' && min.width.val > 0) {
leftVal = leftVal * 100 / min.width.val;
}
var rightVal = min.width.right.value;
if (min.width.right.units === 'px' && min.width.val > 0) {
rightVal = rightVal * 100 / min.width.val;
}
var topVal = min.height.top.value;
if (min.height.top.units === 'px' && min.height.val > 0) {
topVal = topVal * 100 / min.height.val;
}
var bottomVal = min.height.bottom.value;
if (min.height.bottom.units === 'px' && min.height.val > 0) {
bottomVal = bottomVal * 100 / min.height.val;
}
var widthBiasDiffs = computeBiasValues(min.width.val - bb.w, leftVal, rightVal);
var diffLeft = widthBiasDiffs.biasDiff;
var diffRight = widthBiasDiffs.biasComplementDiff;
var heightBiasDiffs = computeBiasValues(min.height.val - bb.h, topVal, bottomVal);
var diffTop = heightBiasDiffs.biasDiff;
var diffBottom = heightBiasDiffs.biasComplementDiff;
_p.autoPadding = computePaddingValues(bb.w, bb.h, parent.pstyle('padding'), parent.pstyle('padding-relative-to').value);
_p.autoWidth = Math.max(bb.w, min.width.val);
pos.x = (-diffLeft + bb.x1 + bb.x2 + diffRight) / 2;
_p.autoHeight = Math.max(bb.h, min.height.val);
pos.y = (-diffTop + bb.y1 + bb.y2 + diffBottom) / 2;
updated.push(parent);
}
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var _p = ele._private;
if (!_p.compoundBoundsClean) {
update(ele);
if (!cy._private.batchingStyle) {
_p.compoundBoundsClean = true;
}
}
}
return this;
};
var noninf = function noninf(x) {
if (x === Infinity || x === -Infinity) {
return 0;
}
return x;
};
var updateBounds = function updateBounds(b, x1, y1, x2, y2) {
// don't update with zero area boxes
if (x2 - x1 === 0 || y2 - y1 === 0) {
return;
}
// don't update with null dim
if (x1 == null || y1 == null || x2 == null || y2 == null) {
return;
}
b.x1 = x1 < b.x1 ? x1 : b.x1;
b.x2 = x2 > b.x2 ? x2 : b.x2;
b.y1 = y1 < b.y1 ? y1 : b.y1;
b.y2 = y2 > b.y2 ? y2 : b.y2;
};
var updateBoundsFromBox = function updateBoundsFromBox(b, b2) {
return updateBounds(b, b2.x1, b2.y1, b2.x2, b2.y2);
};
var prefixedProperty = function prefixedProperty(obj, field, prefix) {
return util.getPrefixedProperty(obj, field, prefix);
};
var updateBoundsFromArrow = function updateBoundsFromArrow(bounds, ele, prefix) {
if (ele.cy().headless()) {
return;
}
var _p = ele._private;
var rstyle = _p.rstyle;
var halfArW = rstyle.arrowWidth / 2;
var arrowType = ele.pstyle(prefix + '-arrow-shape').value;
var x = void 0;
var y = void 0;
if (arrowType !== 'none') {
if (prefix === 'source') {
x = rstyle.srcX;
y = rstyle.srcY;
} else if (prefix === 'target') {
x = rstyle.tgtX;
y = rstyle.tgtY;
} else {
x = rstyle.midX;
y = rstyle.midY;
}
updateBounds(bounds, x - halfArW, y - halfArW, x + halfArW, y + halfArW);
}
};
var updateBoundsFromLabel = function updateBoundsFromLabel(bounds, ele, prefix) {
if (ele.cy().headless()) {
return;
}
var prefixDash = void 0;
if (prefix) {
prefixDash = prefix + '-';
} else {
prefixDash = '';
}
var _p = ele._private;
var rstyle = _p.rstyle;
var label = ele.pstyle(prefixDash + 'label').strValue;
if (label) {
var halign = ele.pstyle('text-halign');
var valign = ele.pstyle('text-valign');
var labelWidth = prefixedProperty(rstyle, 'labelWidth', prefix);
var labelHeight = prefixedProperty(rstyle, 'labelHeight', prefix);
var labelX = prefixedProperty(rstyle, 'labelX', prefix);
var labelY = prefixedProperty(rstyle, 'labelY', prefix);
var marginX = ele.pstyle(prefixDash + 'text-margin-x').pfValue;
var marginY = ele.pstyle(prefixDash + 'text-margin-y').pfValue;
var isEdge = ele.isEdge();
var rotation = ele.pstyle(prefixDash + 'text-rotation');
var outlineWidth = ele.pstyle('text-outline-width').pfValue;
var borderWidth = ele.pstyle('text-border-width').pfValue;
var halfBorderWidth = borderWidth / 2;
var padding = ele.pstyle('text-background-padding').pfValue;
var lh = labelHeight + 2 * padding;
var lw = labelWidth + 2 * padding;
var lw_2 = lw / 2;
var lh_2 = lh / 2;
var lx1 = void 0,
lx2 = void 0,
ly1 = void 0,
ly2 = void 0;
if (isEdge) {
lx1 = labelX - lw_2;
lx2 = labelX + lw_2;
ly1 = labelY - lh_2;
ly2 = labelY + lh_2;
} else {
switch (halign.value) {
case 'left':
lx1 = labelX - lw;
lx2 = labelX;
break;
case 'center':
lx1 = labelX - lw_2;
lx2 = labelX + lw_2;
break;
case 'right':
lx1 = labelX;
lx2 = labelX + lw;
break;
}
switch (valign.value) {
case 'top':
ly1 = labelY - lh;
ly2 = labelY;
break;
case 'center':
ly1 = labelY - lh_2;
ly2 = labelY + lh_2;
break;
case 'bottom':
ly1 = labelY;
ly2 = labelY + lh;
break;
}
}
var isAutorotate = isEdge && rotation.strValue === 'autorotate';
var isPfValue = rotation.pfValue != null && rotation.pfValue !== 0;
if (isAutorotate || isPfValue) {
var theta = isAutorotate ? prefixedProperty(_p.rstyle, 'labelAngle', prefix) : rotation.pfValue;
var cos = Math.cos(theta);
var sin = Math.sin(theta);
var rotate = function rotate(x, y) {
x = x - labelX;
y = y - labelY;
return {
x: x * cos - y * sin + labelX,
y: x * sin + y * cos + labelY
};
};
var px1y1 = rotate(lx1, ly1);
var px1y2 = rotate(lx1, ly2);
var px2y1 = rotate(lx2, ly1);
var px2y2 = rotate(lx2, ly2);
lx1 = Math.min(px1y1.x, px1y2.x, px2y1.x, px2y2.x);
lx2 = Math.max(px1y1.x, px1y2.x, px2y1.x, px2y2.x);
ly1 = Math.min(px1y1.y, px1y2.y, px2y1.y, px2y2.y);
ly2 = Math.max(px1y1.y, px1y2.y, px2y1.y, px2y2.y);
}
lx1 += marginX - Math.max(outlineWidth, halfBorderWidth);
lx2 += marginX + Math.max(outlineWidth, halfBorderWidth);
ly1 += marginY - Math.max(outlineWidth, halfBorderWidth);
ly2 += marginY + Math.max(outlineWidth, halfBorderWidth);
updateBounds(bounds, lx1, ly1, lx2, ly2);
}
return bounds;
};
// get the bounding box of the elements (in raw model position)
var boundingBoxImpl = function boundingBoxImpl(ele, options) {
var cy = ele._private.cy;
var styleEnabled = cy.styleEnabled();
var headless = cy.headless();
var bounds = {
x1: Infinity,
y1: Infinity,
x2: -Infinity,
y2: -Infinity
};
var _p = ele._private;
var display = styleEnabled ? ele.pstyle('display').value : 'element';
var isNode = ele.isNode();
var isEdge = ele.isEdge();
var ex1 = void 0,
ex2 = void 0,
ey1 = void 0,
ey2 = void 0; // extrema of body / lines
var x = void 0,
y = void 0; // node pos
var displayed = display !== 'none';
if (displayed) {
var overlayOpacity = 0;
var overlayPadding = 0;
if (styleEnabled && options.includeOverlays) {
overlayOpacity = ele.pstyle('overlay-opacity').value;
if (overlayOpacity !== 0) {
overlayPadding = ele.pstyle('overlay-padding').value;
}
}
var w = 0;
var wHalf = 0;
if (styleEnabled) {
w = ele.pstyle('width').pfValue;
wHalf = w / 2;
}
if (isNode && options.includeNodes) {
var pos = ele.position();
x = pos.x;
y = pos.y;
var _w = ele.outerWidth();
var halfW = _w / 2;
var h = ele.outerHeight();
var halfH = h / 2;
// handle node dimensions
/////////////////////////
ex1 = x - halfW - overlayPadding;
ex2 = x + halfW + overlayPadding;
ey1 = y - halfH - overlayPadding;
ey2 = y + halfH + overlayPadding;
updateBounds(bounds, ex1, ey1, ex2, ey2);
} else if (isEdge && options.includeEdges) {
var rstyle = _p.rstyle || {};
// handle edge dimensions (rough box estimate)
//////////////////////////////////////////////
if (styleEnabled && !headless) {
ex1 = Math.min(rstyle.srcX, rstyle.midX, rstyle.tgtX);
ex2 = Math.max(rstyle.srcX, rstyle.midX, rstyle.tgtX);
ey1 = Math.min(rstyle.srcY, rstyle.midY, rstyle.tgtY);
ey2 = Math.max(rstyle.srcY, rstyle.midY, rstyle.tgtY);
// take into account edge width
ex1 -= wHalf;
ex2 += wHalf;
ey1 -= wHalf;
ey2 += wHalf;
updateBounds(bounds, ex1, ey1, ex2, ey2);
}
// precise haystacks
////////////////////
if (styleEnabled && !headless && ele.pstyle('curve-style').strValue === 'haystack') {
var hpts = rstyle.haystackPts || [];
ex1 = hpts[0].x;
ey1 = hpts[0].y;
ex2 = hpts[1].x;
ey2 = hpts[1].y;
if (ex1 > ex2) {
var temp = ex1;
ex1 = ex2;
ex2 = temp;
}
if (ey1 > ey2) {
var _temp = ey1;
ey1 = ey2;
ey2 = _temp;
}
updateBounds(bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf);
// handle points along edge
///////////////////////////
} else {
var pts = rstyle.bezierPts || rstyle.linePts || [];
for (var j = 0; j < pts.length; j++) {
var pt = pts[j];
ex1 = pt.x - wHalf;
ex2 = pt.x + wHalf;
ey1 = pt.y - wHalf;
ey2 = pt.y + wHalf;
updateBounds(bounds, ex1, ey1, ex2, ey2);
}
// fallback on source and target positions
//////////////////////////////////////////
if (pts.length === 0) {
var n1 = ele.source();
var n1pos = n1.position();
var n2 = ele.target();
var n2pos = n2.position();
ex1 = n1pos.x;
ex2 = n2pos.x;
ey1 = n1pos.y;
ey2 = n2pos.y;
if (ex1 > ex2) {
var _temp2 = ex1;
ex1 = ex2;
ex2 = _temp2;
}
if (ey1 > ey2) {
var _temp3 = ey1;
ey1 = ey2;
ey2 = _temp3;
}
// take into account edge width
ex1 -= wHalf;
ex2 += wHalf;
ey1 -= wHalf;
ey2 += wHalf;
updateBounds(bounds, ex1, ey1, ex2, ey2);
}
}
} // edges
// handle edge arrow size
/////////////////////////
if (styleEnabled && options.includeEdges && isEdge) {
updateBoundsFromArrow(bounds, ele, 'mid-source', options);
updateBoundsFromArrow(bounds, ele, 'mid-target', options);
updateBoundsFromArrow(bounds, ele, 'source', options);
updateBoundsFromArrow(bounds, ele, 'target', options);
}
// ghost
////////
if (styleEnabled) {
var ghost = ele.pstyle('ghost').value === 'yes';
if (ghost) {
var gx = ele.pstyle('ghost-offset-x').pfValue;
var gy = ele.pstyle('ghost-offset-y').pfValue;
updateBounds(bounds, bounds.x1 + gx, bounds.y1 + gy, bounds.x2 + gx, bounds.y2 + gy);
}
}
// overlay
//////////
if (styleEnabled) {
ex1 = bounds.x1;
ex2 = bounds.x2;
ey1 = bounds.y1;
ey2 = bounds.y2;
updateBounds(bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding);
}
// handle label dimensions
//////////////////////////
if (styleEnabled && options.includeLabels) {
updateBoundsFromLabel(bounds, ele, null, options);
if (isEdge) {
updateBoundsFromLabel(bounds, ele, 'source', options);
updateBoundsFromLabel(bounds, ele, 'target', options);
}
} // style enabled for labels
} // if displayed
bounds.x1 = noninf(bounds.x1);
bounds.y1 = noninf(bounds.y1);
bounds.x2 = noninf(bounds.x2);
bounds.y2 = noninf(bounds.y2);
bounds.w = noninf(bounds.x2 - bounds.x1);
bounds.h = noninf(bounds.y2 - bounds.y1);
// expand bounds by 1 because antialiasing can increase the visual/effective size by 1 on all sides
if (bounds.w > 0 && bounds.h > 0 && displayed) {
math.expandBoundingBox(bounds, 1);
}
return bounds;
};
var tf = function tf(val) {
if (val) {
return 't';
} else {
return 'f';
}
};
var getKey = function getKey(opts) {
var key = '';
key += tf(opts.incudeNodes);
key += tf(opts.includeEdges);
key += tf(opts.includeLabels);
key += tf(opts.includeOverlays);
return key;
};
var cachedBoundingBoxImpl = function cachedBoundingBoxImpl(ele, opts) {
var _p = ele._private;
var bb = void 0;
var headless = ele.cy().headless();
var key = opts === defBbOpts ? defBbOptsKey : getKey(opts);
if (!opts.useCache || headless || !_p.bbCache || !_p.bbCache[key]) {
bb = boundingBoxImpl(ele, opts);
if (!headless) {
_p.bbCache = _p.bbCache || {};
_p.bbCache[key] = bb;
}
} else {
bb = _p.bbCache[key];
}
return bb;
};
var defBbOpts = {
includeNodes: true,
includeEdges: true,
includeLabels: true,
includeOverlays: true,
useCache: true
};
var defBbOptsKey = getKey(defBbOpts);
function filledBbOpts(options) {
return {
includeNodes: util.default(options.includeNodes, defBbOpts.includeNodes),
includeEdges: util.default(options.includeEdges, defBbOpts.includeEdges),
includeLabels: util.default(options.includeLabels, defBbOpts.includeLabels),
includeOverlays: util.default(options.includeOverlays, defBbOpts.includeOverlays),
useCache: util.default(options.useCache, defBbOpts.useCache)
};
}
elesfn.boundingBox = function (options) {
// the main usecase is ele.boundingBox() for a single element with no/def options
// specified s.t. the cache is used, so check for this case to make it faster by
// avoiding the overhead of the rest of the function
if (this.length === 1 && this[0]._private.bbCache && (options === undefined || options.useCache === undefined || options.useCache === true)) {
if (options === undefined) {
options = defBbOpts;
} else {
options = filledBbOpts(options);
}
return cachedBoundingBoxImpl(this[0], options);
}
var bounds = {
x1: Infinity,
y1: Infinity,
x2: -Infinity,
y2: -Infinity
};
options = options || util.staticEmptyObject();
var opts = filledBbOpts(options);
var eles = this;
var cy = eles.cy();
var styleEnabled = cy.styleEnabled();
if (styleEnabled) {
this.recalculateRenderedStyle(opts.useCache);
}
this.updateCompoundBounds();
var updatedEdge = {}; // use to avoid duplicated edge updates
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (styleEnabled && ele.isEdge() && ele.pstyle('curve-style').strValue === 'bezier' && !updatedEdge[ele.id()]) {
var edges = ele.parallelEdges();
for (var j = 0; j < edges.length; j++) {
// make all as updated
updatedEdge[edges[j].id()] = true;
}
edges.recalculateRenderedStyle(opts.useCache); // n.b. ele.parallelEdges() single is cached
}
updateBoundsFromBox(bounds, cachedBoundingBoxImpl(ele, opts));
}
bounds.x1 = noninf(bounds.x1);
bounds.y1 = noninf(bounds.y1);
bounds.x2 = noninf(bounds.x2);
bounds.y2 = noninf(bounds.y2);
bounds.w = noninf(bounds.x2 - bounds.x1);
bounds.h = noninf(bounds.y2 - bounds.y1);
return bounds;
};
// private helper to get bounding box for custom node positions
// - good for perf in certain cases but currently requires dirtying the rendered style
// - would be better to not modify the nodes but the nodes are read directly everywhere in the renderer...
// - try to use for only things like discrete layouts where the node position would change anyway
elesfn.boundingBoxAt = function (fn) {
var nodes = this.nodes();
if (is.plainObject(fn)) {
var obj = fn;
fn = function fn() {
return obj;
};
}
// save the current position and set the new one, per node
for (var i = 0; i < nodes.length; i++) {
var n = nodes[i];
var _p = n._private;
var pos = _p.position;
var newPos = fn.call(n, n, i);
_p.bbAtOldPos = { x: pos.x, y: pos.y };
if (newPos) {
pos.x = newPos.x;
pos.y = newPos.y;
}
}
this.emit('dirty'); // let the renderer know we've manually dirtied rendered dim calcs
nodes.dirtyCompoundBoundsCache().updateCompoundBounds();
var bb = this.boundingBox({ useCache: false });
// restore the original position, per node
for (var _i = 0; _i < nodes.length; _i++) {
var _n = nodes[_i];
var _p2 = _n._private;
var _pos = _n._private.position;
var old = _p2.bbAtOldPos;
_pos.x = old.x;
_pos.y = old.y;
}
nodes.dirtyCompoundBoundsCache();
this.emit('dirty'); // let the renderer know we've manually dirtied rendered dim calcs
return bb;
};
fn.boundingbox = fn.boundingBox;
fn.renderedBoundingbox = fn.renderedBoundingBox;
module.exports = elesfn;
/***/ }),
/* 60 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var fn = void 0,
elesfn = void 0;
fn = elesfn = {};
var defineDimFns = function defineDimFns(opts) {
opts.uppercaseName = util.capitalize(opts.name);
opts.autoName = 'auto' + opts.uppercaseName;
opts.labelName = 'label' + opts.uppercaseName;
opts.outerName = 'outer' + opts.uppercaseName;
opts.uppercaseOuterName = util.capitalize(opts.outerName);
fn[opts.name] = function dimImpl() {
var ele = this[0];
var _p = ele._private;
var cy = _p.cy;
var styleEnabled = cy._private.styleEnabled;
if (ele) {
if (styleEnabled) {
if (ele.isParent()) {
ele.updateCompoundBounds();
return _p[opts.autoName] || 0;
}
var d = ele.pstyle(opts.name);
switch (d.strValue) {
case 'label':
ele.recalculateRenderedStyle();
return _p.rstyle[opts.labelName] || 0;
default:
return d.pfValue;
}
} else {
return 1;
}
}
};
fn['outer' + opts.uppercaseName] = function outerDimImpl() {
var ele = this[0];
var _p = ele._private;
var cy = _p.cy;
var styleEnabled = cy._private.styleEnabled;
if (ele) {
if (styleEnabled) {
var dim = ele[opts.name]();
var border = ele.pstyle('border-width').pfValue; // n.b. 1/2 each side
var padding = 2 * ele.padding();
return dim + border + padding;
} else {
return 1;
}
}
};
fn['rendered' + opts.uppercaseName] = function renderedDimImpl() {
var ele = this[0];
if (ele) {
var d = ele[opts.name]();
return d * this.cy().zoom();
}
};
fn['rendered' + opts.uppercaseOuterName] = function renderedOuterDimImpl() {
var ele = this[0];
if (ele) {
var od = ele[opts.outerName]();
return od * this.cy().zoom();
}
};
};
defineDimFns({
name: 'width'
});
defineDimFns({
name: 'height'
});
elesfn.padding = function () {
var ele = this[0];
var _p = ele._private;
if (ele.isParent()) {
ele.updateCompoundBounds();
if (_p.autoPadding !== undefined) {
return _p.autoPadding;
} else {
return ele.pstyle('padding').pfValue;
}
} else {
return ele.pstyle('padding').pfValue;
}
};
module.exports = elesfn;
/***/ }),
/* 61 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var ifEdge = function ifEdge(self, then) {
if (self.isEdge()) {
return then(self.renderer());
}
};
module.exports = {
controlPoints: function controlPoints() {
var _this = this;
return ifEdge(this, function (renderer) {
return renderer.getControlPoints(_this);
});
},
segmentPoints: function segmentPoints() {
var _this2 = this;
return ifEdge(this, function (renderer) {
return renderer.getSegmentPoints(_this2);
});
},
sourceEndpoint: function sourceEndpoint() {
var _this3 = this;
return ifEdge(this, function (renderer) {
return renderer.getSourceEndpoint(_this3);
});
},
targetEndpoint: function targetEndpoint() {
var _this4 = this;
return ifEdge(this, function (renderer) {
return renderer.getTargetEndpoint(_this4);
});
},
midpoint: function midpoint() {
var _this5 = this;
return ifEdge(this, function (renderer) {
return renderer.getEdgeMidpoint(_this5);
});
}
};
/***/ }),
/* 62 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Emitter = __webpack_require__(11);
var define = __webpack_require__(4);
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Selector = __webpack_require__(6);
var emitterOptions = {
qualifierCompare: function qualifierCompare(selector1, selector2) {
if (selector1 == null || selector2 == null) {
return selector1 == null && selector2 == null;
} else {
return selector1.sameText(selector2);
}
},
eventMatches: function eventMatches(ele, listener, eventObj) {
var selector = listener.qualifier;
if (selector != null) {
return ele !== eventObj.target && is.element(eventObj.target) && selector.matches(eventObj.target);
}
return true;
},
eventFields: function eventFields(ele) {
return {
cy: ele.cy(),
target: ele
};
},
callbackContext: function callbackContext(ele, listener, eventObj) {
return listener.qualifier != null ? eventObj.target : ele;
},
beforeEmit: function beforeEmit(context, listener /*, eventObj*/) {
if (listener.conf && listener.conf.once) {
listener.conf.onceCollection.removeListener(listener.event, listener.qualifier, listener.callback);
}
},
bubble: function bubble() {
return true;
},
parent: function parent(ele) {
return ele.isChild() ? ele.parent() : ele.cy();
}
};
var argSelector = function argSelector(arg) {
if (is.string(arg)) {
return new Selector(arg);
} else {
return arg;
}
};
var elesfn = {
createEmitter: function createEmitter() {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var _p = ele._private;
if (!_p.emitter) {
_p.emitter = new Emitter(util.assign({
context: ele
}, emitterOptions));
}
}
return this;
},
emitter: function emitter() {
return this._private.emitter;
},
on: function on(events, selector, callback) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
ele.emitter().on(events, argSelector(selector), callback);
}
return this;
},
removeListener: function removeListener(events, selector, callback) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
ele.emitter().removeListener(events, argSelector(selector), callback);
}
return this;
},
one: function one(events, selector, callback) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
ele.emitter().one(events, argSelector(selector), callback);
}
return this;
},
once: function once(events, selector, callback) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
ele.emitter().on(events, argSelector(selector), callback, {
once: true,
onceCollection: this
});
}
},
emit: function emit(events, extraParams) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
ele.emitter().emit(events, extraParams);
}
return this;
},
emitAndNotify: function emitAndNotify(event, extraParams) {
// for internal use only
if (this.length === 0) {
return;
} // empty collections don't need to notify anything
// notify renderer
this.cy().notify({
type: event,
eles: this
});
this.emit(event, extraParams);
return this;
}
};
define.eventAliasesOn(elesfn);
module.exports = elesfn;
/***/ }),
/* 63 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Selector = __webpack_require__(6);
var elesfn = {
nodes: function nodes(selector) {
return this.filter(function (ele) {
return ele.isNode();
}).filter(selector);
},
edges: function edges(selector) {
return this.filter(function (ele) {
return ele.isEdge();
}).filter(selector);
},
filter: function filter(_filter, thisArg) {
if (_filter === undefined) {
// check this first b/c it's the most common/performant case
return this;
} else if (is.string(_filter) || is.elementOrCollection(_filter)) {
return new Selector(_filter).filter(this);
} else if (is.fn(_filter)) {
var filterEles = this.spawn();
var eles = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var include = thisArg ? _filter.apply(thisArg, [ele, i, eles]) : _filter(ele, i, eles);
if (include) {
filterEles.merge(ele);
}
}
return filterEles;
}
return this.spawn(); // if not handled by above, give 'em an empty collection
},
not: function not(toRemove) {
if (!toRemove) {
return this;
} else {
if (is.string(toRemove)) {
toRemove = this.filter(toRemove);
}
var elements = [];
var rMap = toRemove._private.map;
for (var i = 0; i < this.length; i++) {
var element = this[i];
var remove = rMap.has(element.id());
if (!remove) {
elements.push(element);
}
}
return this.spawn(elements);
}
},
absoluteComplement: function absoluteComplement() {
var cy = this.cy();
return cy.mutableElements().not(this);
},
intersect: function intersect(other) {
// if a selector is specified, then filter by it instead
if (is.string(other)) {
var selector = other;
return this.filter(selector);
}
var elements = [];
var col1 = this;
var col2 = other;
var col1Smaller = this.length < other.length;
var map2 = col1Smaller ? col2._private.map : col1._private.map;
var col = col1Smaller ? col1 : col2;
for (var i = 0; i < col.length; i++) {
var id = col[i]._private.data.id;
var entry = map2.get(id);
if (entry) {
elements.push(entry.ele);
}
}
return this.spawn(elements);
},
xor: function xor(other) {
var cy = this._private.cy;
if (is.string(other)) {
other = cy.$(other);
}
var elements = [];
var col1 = this;
var col2 = other;
var add = function add(col, other) {
for (var i = 0; i < col.length; i++) {
var ele = col[i];
var id = ele._private.data.id;
var inOther = other.hasElementWithId(id);
if (!inOther) {
elements.push(ele);
}
}
};
add(col1, col2);
add(col2, col1);
return this.spawn(elements);
},
diff: function diff(other) {
var cy = this._private.cy;
if (is.string(other)) {
other = cy.$(other);
}
var left = [];
var right = [];
var both = [];
var col1 = this;
var col2 = other;
var add = function add(col, other, retEles) {
for (var i = 0; i < col.length; i++) {
var ele = col[i];
var id = ele._private.data.id;
var inOther = other.hasElementWithId(id);
if (inOther) {
both.push(ele);
} else {
retEles.push(ele);
}
}
};
add(col1, col2, left);
add(col2, col1, right);
return {
left: this.spawn(left, { unique: true }),
right: this.spawn(right, { unique: true }),
both: this.spawn(both, { unique: true })
};
},
add: function add(toAdd) {
var cy = this._private.cy;
if (!toAdd) {
return this;
}
if (is.string(toAdd)) {
var selector = toAdd;
toAdd = cy.mutableElements().filter(selector);
}
var elements = [];
for (var i = 0; i < this.length; i++) {
elements.push(this[i]);
}
var map = this._private.map;
for (var _i = 0; _i < toAdd.length; _i++) {
var add = !map.has(toAdd[_i].id());
if (add) {
elements.push(toAdd[_i]);
}
}
return this.spawn(elements);
},
// in place merge on calling collection
merge: function merge(toAdd) {
var _p = this._private;
var cy = _p.cy;
if (!toAdd) {
return this;
}
if (toAdd && is.string(toAdd)) {
var selector = toAdd;
toAdd = cy.mutableElements().filter(selector);
}
var map = _p.map;
for (var i = 0; i < toAdd.length; i++) {
var toAddEle = toAdd[i];
var id = toAddEle._private.data.id;
var add = !map.has(id);
if (add) {
var index = this.length++;
this[index] = toAddEle;
map.set(id, { ele: toAddEle, index: index });
} else {
// replace
var _index = map.get(id).index;
this[_index] = toAddEle;
map.set(id, { ele: toAddEle, index: _index });
}
}
return this; // chaining
},
// remove single ele in place in calling collection
unmergeOne: function unmergeOne(ele) {
ele = ele[0];
var _p = this._private;
var id = ele._private.data.id;
var map = _p.map;
var entry = map.get(id);
if (!entry) {
return this; // no need to remove
}
var i = entry.index;
// remove ele
this[i] = undefined;
map.delete(id);
var unmergedLastEle = i === this.length - 1;
// replace empty spot with last ele in collection
if (this.length > 1 && !unmergedLastEle) {
var lastEleI = this.length - 1;
var lastEle = this[lastEleI];
var lastEleId = lastEle._private.data.id;
this[lastEleI] = undefined;
this[i] = lastEle;
map.set(lastEleId, { ele: lastEle, index: i });
}
// the collection is now 1 ele smaller
this.length--;
return this;
},
// remove eles in place on calling collection
unmerge: function unmerge(toRemove) {
var cy = this._private.cy;
if (!toRemove) {
return this;
}
if (toRemove && is.string(toRemove)) {
var selector = toRemove;
toRemove = cy.mutableElements().filter(selector);
}
for (var i = 0; i < toRemove.length; i++) {
this.unmergeOne(toRemove[i]);
}
return this; // chaining
},
map: function map(mapFn, thisArg) {
var arr = [];
var eles = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var ret = thisArg ? mapFn.apply(thisArg, [ele, i, eles]) : mapFn(ele, i, eles);
arr.push(ret);
}
return arr;
},
reduce: function reduce(fn, initialValue) {
var val = initialValue;
var eles = this;
for (var i = 0; i < eles.length; i++) {
val = fn(val, eles[i], i, eles);
}
return val;
},
max: function max(valFn, thisArg) {
var max = -Infinity;
var maxEle = void 0;
var eles = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles);
if (val > max) {
max = val;
maxEle = ele;
}
}
return {
value: max,
ele: maxEle
};
},
min: function min(valFn, thisArg) {
var min = Infinity;
var minEle = void 0;
var eles = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var val = thisArg ? valFn.apply(thisArg, [ele, i, eles]) : valFn(ele, i, eles);
if (val < min) {
min = val;
minEle = ele;
}
}
return {
value: min,
ele: minEle
};
}
};
// aliases
var fn = elesfn;
fn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add;
fn['\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not;
fn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect;
fn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor;
fn.fnFilter = fn.filterFn = fn.stdFilter = fn.filter;
fn.complement = fn.abscomp = fn.absoluteComplement;
module.exports = elesfn;
/***/ }),
/* 64 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var elesfn = {
isNode: function isNode() {
return this.group() === 'nodes';
},
isEdge: function isEdge() {
return this.group() === 'edges';
},
isLoop: function isLoop() {
return this.isEdge() && this.source().id() === this.target().id();
},
isSimple: function isSimple() {
return this.isEdge() && this.source().id() !== this.target().id();
},
group: function group() {
var ele = this[0];
if (ele) {
return ele._private.group;
}
}
};
module.exports = elesfn;
/***/ }),
/* 65 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var zIndexSort = __webpack_require__(17);
var util = __webpack_require__(1);
var elesfn = {
forEach: function forEach(fn, thisArg) {
if (is.fn(fn)) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var ret = thisArg ? fn.apply(thisArg, [ele, i, this]) : fn(ele, i, this);
if (ret === false) {
break;
} // exit each early on return false
}
}
return this;
},
toArray: function toArray() {
var array = [];
for (var i = 0; i < this.length; i++) {
array.push(this[i]);
}
return array;
},
slice: function slice(start, end) {
var array = [];
var thisSize = this.length;
if (end == null) {
end = thisSize;
}
if (start == null) {
start = 0;
}
if (start < 0) {
start = thisSize + start;
}
if (end < 0) {
end = thisSize + end;
}
for (var i = start; i >= 0 && i < end && i < thisSize; i++) {
array.push(this[i]);
}
return this.spawn(array);
},
size: function size() {
return this.length;
},
eq: function eq(i) {
return this[i] || this.spawn();
},
first: function first() {
return this[0] || this.spawn();
},
last: function last() {
return this[this.length - 1] || this.spawn();
},
empty: function empty() {
return this.length === 0;
},
nonempty: function nonempty() {
return !this.empty();
},
sort: function sort(sortFn) {
if (!is.fn(sortFn)) {
return this;
}
var sorted = this.toArray().sort(sortFn);
return this.spawn(sorted);
},
sortByZIndex: function sortByZIndex() {
return this.sort(zIndexSort);
},
zDepth: function zDepth() {
var ele = this[0];
if (!ele) {
return undefined;
}
// let cy = ele.cy();
var _p = ele._private;
var group = _p.group;
if (group === 'nodes') {
var depth = _p.data.parent ? ele.parents().size() : 0;
if (!ele.isParent()) {
return util.MAX_INT - 1; // childless nodes always on top
}
return depth;
} else {
var src = _p.source;
var tgt = _p.target;
var srcDepth = src.zDepth();
var tgtDepth = tgt.zDepth();
return Math.max(srcDepth, tgtDepth, 0); // depth of deepest parent
}
}
};
elesfn.each = elesfn.forEach;
module.exports = elesfn;
/***/ }),
/* 66 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Promise = __webpack_require__(5);
var math = __webpack_require__(2);
var elesfn = {
// Calculates and returns node dimensions { x, y } based on options given
layoutDimensions: function layoutDimensions(options) {
options = util.assign({
nodeDimensionsIncludeLabels: true
}, options);
if (options.nodeDimensionsIncludeLabels) {
var bbDim = this.boundingBox();
return {
w: bbDim.w,
h: bbDim.h
};
} else {
return {
w: this.outerWidth(),
h: this.outerHeight()
};
}
},
// using standard layout options, apply position function (w/ or w/o animation)
layoutPositions: function layoutPositions(layout, options, fn) {
var nodes = this.nodes();
var cy = this.cy();
var layoutEles = options.eles; // nodes & edges
var getMemoizeKey = function getMemoizeKey(node, i) {
return node.id() + '$' + i;
};
var fnMem = util.memoize(fn, getMemoizeKey); // memoized version of position function
layout.emit({ type: 'layoutstart', layout: layout });
layout.animations = [];
var calculateSpacing = function calculateSpacing(spacing, nodesBb, pos) {
var center = {
x: nodesBb.x1 + nodesBb.w / 2,
y: nodesBb.y1 + nodesBb.h / 2
};
var spacingVector = { // scale from center of bounding box (not necessarily 0,0)
x: (pos.x - center.x) * spacing,
y: (pos.y - center.y) * spacing
};
return {
x: center.x + spacingVector.x,
y: center.y + spacingVector.y
};
};
var useSpacingFactor = options.spacingFactor && options.spacingFactor !== 1;
var spacingBb = function spacingBb() {
if (!useSpacingFactor) {
return null;
}
var bb = math.makeBoundingBox();
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var pos = fnMem(node, i);
math.expandBoundingBoxByPoint(bb, pos.x, pos.y);
}
return bb;
};
var bb = spacingBb();
var getFinalPos = util.memoize(function (node, i) {
var newPos = fnMem(node, i);
var pos = node.position();
if (!is.number(pos.x) || !is.number(pos.y)) {
node.silentPosition({ x: 0, y: 0 });
}
if (useSpacingFactor) {
var spacing = Math.abs(options.spacingFactor);
newPos = calculateSpacing(spacing, bb, newPos);
}
if (options.transform != null) {
newPos = options.transform(node, newPos);
}
return newPos;
}, getMemoizeKey);
if (options.animate) {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var newPos = getFinalPos(node, i);
var animateNode = options.animateFilter == null || options.animateFilter(node, i);
if (animateNode) {
var ani = node.animation({
position: newPos,
duration: options.animationDuration,
easing: options.animationEasing
});
layout.animations.push(ani);
ani.play();
} else {
node.position(newPos);
}
}
if (options.fit) {
var fitAni = cy.animation({
fit: {
boundingBox: layoutEles.boundingBoxAt(getFinalPos),
padding: options.padding
},
duration: options.animationDuration,
easing: options.animationEasing
});
layout.animations.push(fitAni);
fitAni.play();
} else if (options.zoom !== undefined && options.pan !== undefined) {
var zoomPanAni = cy.animation({
zoom: options.zoom,
pan: options.pan,
duration: options.animationDuration,
easing: options.animationEasing
});
layout.animations.push(zoomPanAni);
zoomPanAni.play();
}
layout.one('layoutready', options.ready);
layout.emit({ type: 'layoutready', layout: layout });
Promise.all(layout.animations.map(function (ani) {
return ani.promise();
})).then(function () {
layout.one('layoutstop', options.stop);
layout.emit({ type: 'layoutstop', layout: layout });
});
} else {
nodes.positions(getFinalPos);
if (options.fit) {
cy.fit(options.eles, options.padding);
}
if (options.zoom != null) {
cy.zoom(options.zoom);
}
if (options.pan) {
cy.pan(options.pan);
}
layout.one('layoutready', options.ready);
layout.emit({ type: 'layoutready', layout: layout });
layout.one('layoutstop', options.stop);
layout.emit({ type: 'layoutstop', layout: layout });
}
return this; // chaining
},
layout: function layout(options) {
var cy = this.cy();
return cy.makeLayout(util.extend({}, options, {
eles: this
}));
}
};
// aliases:
elesfn.createLayout = elesfn.makeLayout = elesfn.layout;
module.exports = elesfn;
/***/ }),
/* 67 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
function styleCache(key, fn, ele) {
var _p = ele._private;
var cache = _p.styleCache = _p.styleCache || {};
var val;
if ((val = cache[key]) != null) {
return val;
} else {
val = cache[key] = fn(ele);
return val;
}
}
function cacheStyleFunction(key, fn) {
return function cachedStyleFunction(ele) {
return styleCache(key, fn, ele);
};
}
function cachePrototypeStyleFunction(key, fn) {
var selfFn = function selfFn(ele) {
return fn.call(ele);
};
return function cachedPrototypeStyleFunction() {
var ele = this[0];
if (ele) {
return styleCache(key, selfFn, ele);
}
};
}
var elesfn = {
recalculateRenderedStyle: function recalculateRenderedStyle(useCache) {
var cy = this.cy();
var renderer = cy.renderer();
var styleEnabled = cy.styleEnabled();
if (renderer && styleEnabled) {
renderer.recalculateRenderedStyle(this, useCache);
}
return this;
},
dirtyStyleCache: function dirtyStyleCache() {
var cy = this.cy();
var dirty = function dirty(ele) {
return ele._private.styleCache = {};
};
if (cy.hasCompoundNodes()) {
var eles = void 0;
eles = this.spawnSelf().merge(this.descendants()).merge(this.parents());
eles.merge(eles.connectedEdges());
eles.forEach(dirty);
} else {
this.forEach(function (ele) {
dirty(ele);
ele.connectedEdges().forEach(dirty);
});
}
return this;
},
// fully updates (recalculates) the style for the elements
updateStyle: function updateStyle(notifyRenderer) {
var cy = this._private.cy;
if (!cy.styleEnabled()) {
return this;
}
if (cy._private.batchingStyle) {
var bEles = cy._private.batchStyleEles;
bEles.merge(this);
return this; // chaining and exit early when batching
}
var hasCompounds = cy.hasCompoundNodes();
var style = cy.style();
var updatedEles = this;
notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;
if (hasCompounds) {
// then add everything up and down for compound selector checks
updatedEles = this.spawnSelf().merge(this.descendants()).merge(this.parents());
}
var changedEles = style.apply(updatedEles);
changedEles.dirtyStyleCache();
changedEles.dirtyCompoundBoundsCache();
if (notifyRenderer) {
changedEles.emitAndNotify('style'); // let renderer know we changed style
} else {
changedEles.emit('style'); // just fire the event
}
return this; // chaining
},
// just update the mappers in the elements' styles; cheaper than eles.updateStyle()
updateMappers: function updateMappers(notifyRenderer) {
var cy = this._private.cy;
var style = cy.style();
notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;
if (!cy.styleEnabled()) {
return this;
}
var changedEles = style.updateMappers(this);
changedEles.dirtyStyleCache();
changedEles.dirtyCompoundBoundsCache();
if (notifyRenderer) {
changedEles.emitAndNotify('style'); // let renderer know we changed style
} else {
changedEles.emit('style'); // just fire the event
}
return this; // chaining
},
// get the internal parsed style object for the specified property
parsedStyle: function parsedStyle(property) {
var ele = this[0];
var cy = ele.cy();
if (!cy.styleEnabled()) {
return;
}
if (ele) {
return ele._private.style[property] || cy.style().getDefaultProperty(property);
}
},
numericStyle: function numericStyle(property) {
var ele = this[0];
if (!ele.cy().styleEnabled()) {
return;
}
if (ele) {
var pstyle = ele.pstyle(property);
return pstyle.pfValue !== undefined ? pstyle.pfValue : pstyle.value;
}
},
numericStyleUnits: function numericStyleUnits(property) {
var ele = this[0];
if (!ele.cy().styleEnabled()) {
return;
}
if (ele) {
return ele.pstyle(property).units;
}
},
// get the specified css property as a rendered value (i.e. on-screen value)
// or get the whole rendered style if no property specified (NB doesn't allow setting)
renderedStyle: function renderedStyle(property) {
var cy = this.cy();
if (!cy.styleEnabled()) {
return this;
}
var ele = this[0];
if (ele) {
return cy.style().getRenderedStyle(ele, property);
}
},
// read the calculated css style of the element or override the style (via a bypass)
style: function style(name, value) {
var cy = this.cy();
if (!cy.styleEnabled()) {
return this;
}
var updateTransitions = false;
var style = cy.style();
if (is.plainObject(name)) {
// then extend the bypass
var props = name;
style.applyBypass(this, props, updateTransitions);
this.dirtyStyleCache();
this.dirtyCompoundBoundsCache();
this.emitAndNotify('style'); // let the renderer know we've updated style
} else if (is.string(name)) {
if (value === undefined) {
// then get the property from the style
var ele = this[0];
if (ele) {
return style.getStylePropertyValue(ele, name);
} else {
// empty collection => can't get any value
return;
}
} else {
// then set the bypass with the property value
style.applyBypass(this, name, value, updateTransitions);
this.dirtyStyleCache();
this.dirtyCompoundBoundsCache();
this.emitAndNotify('style'); // let the renderer know we've updated style
}
} else if (name === undefined) {
var _ele = this[0];
if (_ele) {
return style.getRawStyle(_ele);
} else {
// empty collection => can't get any value
return;
}
}
return this; // chaining
},
removeStyle: function removeStyle(names) {
var cy = this.cy();
if (!cy.styleEnabled()) {
return this;
}
var updateTransitions = false;
var style = cy.style();
var eles = this;
if (names === undefined) {
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
style.removeAllBypasses(ele, updateTransitions);
}
} else {
names = names.split(/\s+/);
for (var _i = 0; _i < eles.length; _i++) {
var _ele2 = eles[_i];
style.removeBypasses(_ele2, names, updateTransitions);
}
}
this.dirtyStyleCache();
this.dirtyCompoundBoundsCache();
this.emitAndNotify('style'); // let the renderer know we've updated style
return this; // chaining
},
show: function show() {
this.css('display', 'element');
return this; // chaining
},
hide: function hide() {
this.css('display', 'none');
return this; // chaining
},
effectiveOpacity: function effectiveOpacity() {
var cy = this.cy();
if (!cy.styleEnabled()) {
return 1;
}
var hasCompoundNodes = cy.hasCompoundNodes();
var ele = this[0];
if (ele) {
var _p = ele._private;
var parentOpacity = ele.pstyle('opacity').value;
if (!hasCompoundNodes) {
return parentOpacity;
}
var parents = !_p.data.parent ? null : ele.parents();
if (parents) {
for (var i = 0; i < parents.length; i++) {
var parent = parents[i];
var opacity = parent.pstyle('opacity').value;
parentOpacity = opacity * parentOpacity;
}
}
return parentOpacity;
}
},
transparent: function transparent() {
var cy = this.cy();
if (!cy.styleEnabled()) {
return false;
}
var ele = this[0];
var hasCompoundNodes = ele.cy().hasCompoundNodes();
if (ele) {
if (!hasCompoundNodes) {
return ele.pstyle('opacity').value === 0;
} else {
return ele.effectiveOpacity() === 0;
}
}
},
backgrounding: function backgrounding() {
var cy = this.cy();
if (!cy.styleEnabled()) {
return false;
}
var ele = this[0];
return ele._private.backgrounding ? true : false;
}
};
function checkCompound(ele, parentOk) {
var _p = ele._private;
var parents = _p.data.parent ? ele.parents() : null;
if (parents) {
for (var i = 0; i < parents.length; i++) {
var parent = parents[i];
if (!parentOk(parent)) {
return false;
}
}
}
return true;
}
function defineDerivedStateFunction(specs) {
var ok = specs.ok;
var edgeOkViaNode = specs.edgeOkViaNode || specs.ok;
var parentOk = specs.parentOk || specs.ok;
return function () {
var cy = this.cy();
if (!cy.styleEnabled()) {
return true;
}
var ele = this[0];
var hasCompoundNodes = cy.hasCompoundNodes();
if (ele) {
var _p = ele._private;
if (!ok(ele)) {
return false;
}
if (ele.isNode()) {
return !hasCompoundNodes || checkCompound(ele, parentOk);
} else {
var src = _p.source;
var tgt = _p.target;
return edgeOkViaNode(src) && (!hasCompoundNodes || checkCompound(src, edgeOkViaNode)) && (src === tgt || edgeOkViaNode(tgt) && (!hasCompoundNodes || checkCompound(tgt, edgeOkViaNode)));
}
}
};
}
var eleTakesUpSpace = cacheStyleFunction('eleTakesUpSpace', function (ele) {
return ele.pstyle('display').value === 'element' && ele.width() !== 0 && (ele.isNode() ? ele.height() !== 0 : true);
});
elesfn.takesUpSpace = cachePrototypeStyleFunction('takesUpSpace', defineDerivedStateFunction({
ok: eleTakesUpSpace
}));
var eleInteractive = cacheStyleFunction('eleInteractive', function (ele) {
return ele.pstyle('events').value === 'yes' && ele.pstyle('visibility').value === 'visible' && eleTakesUpSpace(ele);
});
var parentInteractive = cacheStyleFunction('parentInteractive', function (parent) {
return parent.pstyle('visibility').value === 'visible' && eleTakesUpSpace(parent);
});
elesfn.interactive = cachePrototypeStyleFunction('interactive', defineDerivedStateFunction({
ok: eleInteractive,
parentOk: parentInteractive,
edgeOkViaNode: eleTakesUpSpace
}));
elesfn.noninteractive = function () {
var ele = this[0];
if (ele) {
return !ele.interactive();
}
};
var eleVisible = cacheStyleFunction('eleVisible', function (ele) {
return ele.pstyle('visibility').value === 'visible' && ele.pstyle('opacity').pfValue !== 0 && eleTakesUpSpace(ele);
});
var edgeVisibleViaNode = eleTakesUpSpace;
elesfn.visible = cachePrototypeStyleFunction('visible', defineDerivedStateFunction({
ok: eleVisible,
edgeOkViaNode: edgeVisibleViaNode
}));
elesfn.hidden = function () {
var ele = this[0];
if (ele) {
return !ele.visible();
}
};
elesfn.bypass = elesfn.css = elesfn.style;
elesfn.renderedCss = elesfn.renderedStyle;
elesfn.removeBypass = elesfn.removeCss = elesfn.removeStyle;
elesfn.pstyle = elesfn.parsedStyle;
module.exports = elesfn;
/***/ }),
/* 68 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var elesfn = {};
function defineSwitchFunction(params) {
return function () {
var args = arguments;
var changedEles = [];
// e.g. cy.nodes().select( data, handler )
if (args.length === 2) {
var data = args[0];
var handler = args[1];
this.on(params.event, data, handler);
}
// e.g. cy.nodes().select( handler )
else if (args.length === 1) {
var _handler = args[0];
this.on(params.event, _handler);
}
// e.g. cy.nodes().select()
else if (args.length === 0) {
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var able = !params.ableField || ele._private[params.ableField];
var changed = ele._private[params.field] != params.value;
if (params.overrideAble) {
var overrideAble = params.overrideAble(ele);
if (overrideAble !== undefined) {
able = overrideAble;
if (!overrideAble) {
return this;
} // to save cycles assume not able for all on override
}
}
if (able) {
ele._private[params.field] = params.value;
if (changed) {
changedEles.push(ele);
}
}
}
var changedColl = this.spawn(changedEles);
changedColl.updateStyle(); // change of state => possible change of style
changedColl.emit(params.event);
}
return this;
};
}
function defineSwitchSet(params) {
elesfn[params.field] = function () {
var ele = this[0];
if (ele) {
if (params.overrideField) {
var val = params.overrideField(ele);
if (val !== undefined) {
return val;
}
}
return ele._private[params.field];
}
};
elesfn[params.on] = defineSwitchFunction({
event: params.on,
field: params.field,
ableField: params.ableField,
overrideAble: params.overrideAble,
value: true
});
elesfn[params.off] = defineSwitchFunction({
event: params.off,
field: params.field,
ableField: params.ableField,
overrideAble: params.overrideAble,
value: false
});
}
defineSwitchSet({
field: 'locked',
overrideField: function overrideField(ele) {
return ele.cy().autolock() ? true : undefined;
},
on: 'lock',
off: 'unlock'
});
defineSwitchSet({
field: 'grabbable',
overrideField: function overrideField(ele) {
return ele.cy().autoungrabify() ? false : undefined;
},
on: 'grabify',
off: 'ungrabify'
});
defineSwitchSet({
field: 'selected',
ableField: 'selectable',
overrideAble: function overrideAble(ele) {
return ele.cy().autounselectify() ? false : undefined;
},
on: 'select',
off: 'unselect'
});
defineSwitchSet({
field: 'selectable',
overrideField: function overrideField(ele) {
return ele.cy().autounselectify() ? false : undefined;
},
on: 'selectify',
off: 'unselectify'
});
elesfn.deselect = elesfn.unselect;
elesfn.grabbed = function () {
var ele = this[0];
if (ele) {
return ele._private.grabbed;
}
};
defineSwitchSet({
field: 'active',
on: 'activate',
off: 'unactivate'
});
elesfn.inactive = function () {
var ele = this[0];
if (ele) {
return !ele._private.active;
}
};
module.exports = elesfn;
/***/ }),
/* 69 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var elesfn = {};
var cache = function cache(fn, name) {
return function traversalCache(arg1, arg2, arg3, arg4) {
var selectorOrEles = arg1;
var eles = this;
var key = void 0;
if (selectorOrEles == null) {
key = 'null';
} else if (is.elementOrCollection(selectorOrEles) && selectorOrEles.length === 1) {
key = '#' + selectorOrEles.id();
}
if (eles.length === 1 && key) {
var _p = eles[0]._private;
var tch = _p.traversalCache = _p.traversalCache || {};
var ch = tch[name] = tch[name] || {};
var cacheHit = ch[key];
if (cacheHit) {
return cacheHit;
} else {
return ch[key] = fn.call(eles, arg1, arg2, arg3, arg4);
}
} else {
return fn.call(eles, arg1, arg2, arg3, arg4);
}
};
};
// DAG functions
////////////////
var defineDagExtremity = function defineDagExtremity(params) {
return function dagExtremityImpl(selector) {
var eles = this;
var ret = [];
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (!ele.isNode()) {
continue;
}
var disqualified = false;
var edges = ele.connectedEdges();
for (var j = 0; j < edges.length; j++) {
var edge = edges[j];
var src = edge.source();
var tgt = edge.target();
if (params.noIncomingEdges && tgt === ele && src !== ele || params.noOutgoingEdges && src === ele && tgt !== ele) {
disqualified = true;
break;
}
}
if (!disqualified) {
ret.push(ele);
}
}
return this.spawn(ret, { unique: true }).filter(selector);
};
};
var defineDagOneHop = function defineDagOneHop(params) {
return function (selector) {
var eles = this;
var oEles = [];
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (!ele.isNode()) {
continue;
}
var edges = ele.connectedEdges();
for (var j = 0; j < edges.length; j++) {
var edge = edges[j];
var src = edge.source();
var tgt = edge.target();
if (params.outgoing && src === ele) {
oEles.push(edge);
oEles.push(tgt);
} else if (params.incoming && tgt === ele) {
oEles.push(edge);
oEles.push(src);
}
}
}
return this.spawn(oEles, { unique: true }).filter(selector);
};
};
var defineDagAllHops = function defineDagAllHops(params) {
return function (selector) {
var eles = this;
var sEles = [];
var sElesIds = {};
for (;;) {
var next = params.outgoing ? eles.outgoers() : eles.incomers();
if (next.length === 0) {
break;
} // done if none left
var newNext = false;
for (var i = 0; i < next.length; i++) {
var n = next[i];
var nid = n.id();
if (!sElesIds[nid]) {
sElesIds[nid] = true;
sEles.push(n);
newNext = true;
}
}
if (!newNext) {
break;
} // done if touched all outgoers already
eles = next;
}
return this.spawn(sEles, { unique: true }).filter(selector);
};
};
elesfn.clearTraversalCache = function () {
for (var i = 0; i < this.length; i++) {
this[i]._private.traversalCache = null;
}
};
util.extend(elesfn, {
// get the root nodes in the DAG
roots: defineDagExtremity({ noIncomingEdges: true }),
// get the leaf nodes in the DAG
leaves: defineDagExtremity({ noOutgoingEdges: true }),
// normally called children in graph theory
// these nodes =edges=> outgoing nodes
outgoers: cache(defineDagOneHop({ outgoing: true }), 'outgoers'),
// aka DAG descendants
successors: defineDagAllHops({ outgoing: true }),
// normally called parents in graph theory
// these nodes <=edges= incoming nodes
incomers: cache(defineDagOneHop({ incoming: true }), 'incomers'),
// aka DAG ancestors
predecessors: defineDagAllHops({ incoming: true })
});
// Neighbourhood functions
//////////////////////////
util.extend(elesfn, {
neighborhood: cache(function (selector) {
var elements = [];
var nodes = this.nodes();
for (var i = 0; i < nodes.length; i++) {
// for all nodes
var node = nodes[i];
var connectedEdges = node.connectedEdges();
// for each connected edge, add the edge and the other node
for (var j = 0; j < connectedEdges.length; j++) {
var edge = connectedEdges[j];
var src = edge.source();
var tgt = edge.target();
var otherNode = node === src ? tgt : src;
// need check in case of loop
if (otherNode.length > 0) {
elements.push(otherNode[0]); // add node 1 hop away
}
// add connected edge
elements.push(edge[0]);
}
}
return this.spawn(elements, { unique: true }).filter(selector);
}, 'neighborhood'),
closedNeighborhood: function closedNeighborhood(selector) {
return this.neighborhood().add(this).filter(selector);
},
openNeighborhood: function openNeighborhood(selector) {
return this.neighborhood(selector);
}
});
// aliases
elesfn.neighbourhood = elesfn.neighborhood;
elesfn.closedNeighbourhood = elesfn.closedNeighborhood;
elesfn.openNeighbourhood = elesfn.openNeighborhood;
// Edge functions
/////////////////
util.extend(elesfn, {
source: cache(function sourceImpl(selector) {
var ele = this[0];
var src = void 0;
if (ele) {
src = ele._private.source || ele.cy().collection();
}
return src && selector ? src.filter(selector) : src;
}, 'source'),
target: cache(function targetImpl(selector) {
var ele = this[0];
var tgt = void 0;
if (ele) {
tgt = ele._private.target || ele.cy().collection();
}
return tgt && selector ? tgt.filter(selector) : tgt;
}, 'target'),
sources: defineSourceFunction({
attr: 'source'
}),
targets: defineSourceFunction({
attr: 'target'
})
});
function defineSourceFunction(params) {
return function sourceImpl(selector) {
var sources = [];
for (var i = 0; i < this.length; i++) {
var ele = this[i];
var src = ele._private[params.attr];
if (src) {
sources.push(src);
}
}
return this.spawn(sources, { unique: true }).filter(selector);
};
}
util.extend(elesfn, {
edgesWith: cache(defineEdgesWithFunction(), 'edgesWith'),
edgesTo: cache(defineEdgesWithFunction({
thisIsSrc: true
}), 'edgesTo')
});
function defineEdgesWithFunction(params) {
return function edgesWithImpl(otherNodes) {
var elements = [];
var cy = this._private.cy;
var p = params || {};
// get elements if a selector is specified
if (is.string(otherNodes)) {
otherNodes = cy.$(otherNodes);
}
for (var h = 0; h < otherNodes.length; h++) {
var edges = otherNodes[h]._private.edges;
for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var edgeData = edge._private.data;
var thisToOther = this.hasElementWithId(edgeData.source) && otherNodes.hasElementWithId(edgeData.target);
var otherToThis = otherNodes.hasElementWithId(edgeData.source) && this.hasElementWithId(edgeData.target);
var edgeConnectsThisAndOther = thisToOther || otherToThis;
if (!edgeConnectsThisAndOther) {
continue;
}
if (p.thisIsSrc || p.thisIsTgt) {
if (p.thisIsSrc && !thisToOther) {
continue;
}
if (p.thisIsTgt && !otherToThis) {
continue;
}
}
elements.push(edge);
}
}
return this.spawn(elements, { unique: true });
};
}
util.extend(elesfn, {
connectedEdges: cache(function (selector) {
var retEles = [];
var eles = this;
for (var i = 0; i < eles.length; i++) {
var node = eles[i];
if (!node.isNode()) {
continue;
}
var edges = node._private.edges;
for (var j = 0; j < edges.length; j++) {
var edge = edges[j];
retEles.push(edge);
}
}
return this.spawn(retEles, { unique: true }).filter(selector);
}, 'connectedEdges'),
connectedNodes: cache(function (selector) {
var retEles = [];
var eles = this;
for (var i = 0; i < eles.length; i++) {
var edge = eles[i];
if (!edge.isEdge()) {
continue;
}
retEles.push(edge.source()[0]);
retEles.push(edge.target()[0]);
}
return this.spawn(retEles, { unique: true }).filter(selector);
}, 'connectedNodes'),
parallelEdges: cache(defineParallelEdgesFunction(), 'parallelEdges'),
codirectedEdges: cache(defineParallelEdgesFunction({
codirected: true
}), 'codirectedEdges')
});
function defineParallelEdgesFunction(params) {
var defaults = {
codirected: false
};
params = util.extend({}, defaults, params);
return function parallelEdgesImpl(selector) {
// micro-optimised for renderer
var elements = [];
var edges = this.edges();
var p = params;
// look at all the edges in the collection
for (var i = 0; i < edges.length; i++) {
var edge1 = edges[i];
var edge1_p = edge1._private;
var src1 = edge1_p.source;
var srcid1 = src1._private.data.id;
var tgtid1 = edge1_p.data.target;
var srcEdges1 = src1._private.edges;
// look at edges connected to the src node of this edge
for (var j = 0; j < srcEdges1.length; j++) {
var edge2 = srcEdges1[j];
var edge2data = edge2._private.data;
var tgtid2 = edge2data.target;
var srcid2 = edge2data.source;
var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;
var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;
if (p.codirected && codirected || !p.codirected && (codirected || oppdirected)) {
elements.push(edge2);
}
}
}
return this.spawn(elements, { unique: true }).filter(selector);
};
}
// Misc functions
/////////////////
util.extend(elesfn, {
components: function components() {
var self = this;
var cy = self.cy();
var visited = self.spawn();
var unvisited = self.nodes().spawnSelf();
var components = [];
var visitInComponent = function visitInComponent(node, component) {
visited.merge(node);
unvisited.unmerge(node);
component.merge(node);
};
if (unvisited.empty()) {
return self.spawn();
}
var _loop = function _loop() {
var component = cy.collection();
components.push(component);
var root = unvisited[0];
visitInComponent(root, component);
self.bfs({
directed: false,
roots: root,
visit: function visit(v, e, u, i, depth) {
visitInComponent(v, component);
}
});
};
do {
_loop();
} while (unvisited.length > 0);
return components.map(function (component) {
var connectedEdges = component.connectedEdges().stdFilter(function (edge) {
return component.anySame(edge.source()) && component.anySame(edge.target());
});
return component.union(connectedEdges);
});
}
});
module.exports = elesfn;
/***/ }),
/* 70 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Collection = __webpack_require__(7);
var Element = __webpack_require__(14);
var corefn = {
add: function add(opts) {
var elements = void 0;
var cy = this;
// add the elements
if (is.elementOrCollection(opts)) {
var eles = opts;
if (eles._private.cy === cy) {
// same instance => just restore
elements = eles.restore();
} else {
// otherwise, copy from json
var jsons = [];
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
jsons.push(ele.json());
}
elements = new Collection(cy, jsons);
}
}
// specify an array of options
else if (is.array(opts)) {
var _jsons = opts;
elements = new Collection(cy, _jsons);
}
// specify via opts.nodes and opts.edges
else if (is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges))) {
var elesByGroup = opts;
var _jsons2 = [];
var grs = ['nodes', 'edges'];
for (var _i = 0, il = grs.length; _i < il; _i++) {
var group = grs[_i];
var elesArray = elesByGroup[group];
if (is.array(elesArray)) {
for (var j = 0, jl = elesArray.length; j < jl; j++) {
var json = util.extend({ group: group }, elesArray[j]);
_jsons2.push(json);
}
}
}
elements = new Collection(cy, _jsons2);
}
// specify options for one element
else {
var _json = opts;
elements = new Element(cy, _json).collection();
}
return elements;
},
remove: function remove(collection) {
if (is.elementOrCollection(collection)) {
// already have right ref
} else if (is.string(collection)) {
var selector = collection;
collection = this.$(selector);
}
return collection.remove();
}
};
module.exports = corefn;
/***/ }),
/* 71 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var define = __webpack_require__(4);
var util = __webpack_require__(1);
var stepAll = __webpack_require__(72);
var corefn = {
// pull in animation functions
animate: define.animate(),
animation: define.animation(),
animated: define.animated(),
clearQueue: define.clearQueue(),
delay: define.delay(),
delayAnimation: define.delayAnimation(),
stop: define.stop(),
addToAnimationPool: function addToAnimationPool(eles) {
var cy = this;
if (!cy.styleEnabled()) {
return;
} // save cycles when no style used
cy._private.aniEles.merge(eles);
},
stopAnimationLoop: function stopAnimationLoop() {
this._private.animationsRunning = false;
},
startAnimationLoop: function startAnimationLoop() {
var cy = this;
cy._private.animationsRunning = true;
if (!cy.styleEnabled()) {
return;
} // save cycles when no style used
// NB the animation loop will exec in headless environments if style enabled
// and explicit cy.destroy() is necessary to stop the loop
function headlessStep() {
if (!cy._private.animationsRunning) {
return;
}
util.requestAnimationFrame(function animationStep(now) {
stepAll(now, cy);
headlessStep();
});
}
var renderer = cy.renderer();
if (renderer && renderer.beforeRender) {
// let the renderer schedule animations
renderer.beforeRender(function rendererAnimationStep(willDraw, now) {
stepAll(now, cy);
}, renderer.beforeRenderPriorities.animations);
} else {
// manage the animation loop ourselves
headlessStep(); // first call
}
}
};
module.exports = corefn;
/***/ }),
/* 72 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var step = __webpack_require__(73);
var startAnimation = __webpack_require__(78);
function stepAll(now, cy) {
var eles = cy._private.aniEles;
var doneEles = [];
function stepOne(ele, isCore) {
var _p = ele._private;
var current = _p.animation.current;
var queue = _p.animation.queue;
var ranAnis = false;
// cancel all animations on display:none ele
if (!isCore && ele.pstyle('display').value === 'none') {
// put all current and queue animations in this tick's current list
// and empty the lists for the element
current = current.splice(0, current.length).concat(queue.splice(0, queue.length));
// stop all animations
for (var i = 0; i < current.length; i++) {
current[i].stop();
}
}
// if nothing currently animating, get something from the queue
if (current.length === 0) {
var next = queue.shift();
if (next) {
current.push(next);
}
}
var callbacks = function callbacks(_callbacks) {
for (var j = _callbacks.length - 1; j >= 0; j--) {
var cb = _callbacks[j];
cb();
}
_callbacks.splice(0, _callbacks.length);
};
// step and remove if done
for (var _i = current.length - 1; _i >= 0; _i--) {
var ani = current[_i];
var ani_p = ani._private;
if (ani_p.stopped) {
current.splice(_i, 1);
ani_p.hooked = false;
ani_p.playing = false;
ani_p.started = false;
callbacks(ani_p.frames);
continue;
}
if (!ani_p.playing && !ani_p.applying) {
continue;
}
// an apply() while playing shouldn't do anything
if (ani_p.playing && ani_p.applying) {
ani_p.applying = false;
}
if (!ani_p.started) {
startAnimation(ele, ani, now, isCore);
}
step(ele, ani, now, isCore);
if (ani_p.applying) {
ani_p.applying = false;
}
callbacks(ani_p.frames);
if (ani.completed()) {
current.splice(_i, 1);
ani_p.hooked = false;
ani_p.playing = false;
ani_p.started = false;
callbacks(ani_p.completes);
}
ranAnis = true;
}
if (!isCore && current.length === 0 && queue.length === 0) {
doneEles.push(ele);
}
return ranAnis;
} // stepElement
// handle all eles
var ranEleAni = false;
for (var e = 0; e < eles.length; e++) {
var ele = eles[e];
var handledThisEle = stepOne(ele);
ranEleAni = ranEleAni || handledThisEle;
} // each element
var ranCoreAni = stepOne(cy, true);
// notify renderer
if (ranEleAni || ranCoreAni) {
if (eles.length > 0) {
eles.dirtyCompoundBoundsCache();
cy.notify({
type: 'draw',
eles: eles
});
} else {
cy.notify({
type: 'draw'
});
}
}
// remove elements from list of currently animating if its queues are empty
eles.unmerge(doneEles);
cy.emit('step');
} // stepAll
module.exports = stepAll;
/***/ }),
/* 73 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var easings = __webpack_require__(74);
var ease = __webpack_require__(77);
var is = __webpack_require__(0);
function step(self, ani, now, isCore) {
var isEles = !isCore;
var _p = self._private;
var ani_p = ani._private;
var pEasing = ani_p.easing;
var startTime = ani_p.startTime;
var cy = isCore ? self : self.cy();
var style = cy.style();
if (!ani_p.easingImpl) {
if (pEasing == null) {
// use default
ani_p.easingImpl = easings['linear'];
} else {
// then define w/ name
var easingVals = void 0;
if (is.string(pEasing)) {
var easingProp = style.parse('transition-timing-function', pEasing);
easingVals = easingProp.value;
} else {
// then assume preparsed array
easingVals = pEasing;
}
var name = void 0,
args = void 0;
if (is.string(easingVals)) {
name = easingVals;
args = [];
} else {
name = easingVals[1];
args = easingVals.slice(2).map(function (n) {
return +n;
});
}
if (args.length > 0) {
// create with args
if (name === 'spring') {
args.push(ani_p.duration); // need duration to generate spring
}
ani_p.easingImpl = easings[name].apply(null, args);
} else {
// static impl by name
ani_p.easingImpl = easings[name];
}
}
}
var easing = ani_p.easingImpl;
var percent = void 0;
if (ani_p.duration === 0) {
percent = 1;
} else {
percent = (now - startTime) / ani_p.duration;
}
if (ani_p.applying) {
percent = ani_p.progress;
}
if (percent < 0) {
percent = 0;
} else if (percent > 1) {
percent = 1;
}
if (ani_p.delay == null) {
// then update
var startPos = ani_p.startPosition;
var endPos = ani_p.position;
if (endPos && isEles && !self.locked()) {
var pos = self.position();
if (valid(startPos.x, endPos.x)) {
pos.x = ease(startPos.x, endPos.x, percent, easing);
}
if (valid(startPos.y, endPos.y)) {
pos.y = ease(startPos.y, endPos.y, percent, easing);
}
self.emit('position');
}
var startPan = ani_p.startPan;
var endPan = ani_p.pan;
var pan = _p.pan;
var animatingPan = endPan != null && isCore;
if (animatingPan) {
if (valid(startPan.x, endPan.x)) {
pan.x = ease(startPan.x, endPan.x, percent, easing);
}
if (valid(startPan.y, endPan.y)) {
pan.y = ease(startPan.y, endPan.y, percent, easing);
}
self.emit('pan');
}
var startZoom = ani_p.startZoom;
var endZoom = ani_p.zoom;
var animatingZoom = endZoom != null && isCore;
if (animatingZoom) {
if (valid(startZoom, endZoom)) {
_p.zoom = ease(startZoom, endZoom, percent, easing);
}
self.emit('zoom');
}
if (animatingPan || animatingZoom) {
self.emit('viewport');
}
var props = ani_p.style;
if (props && props.length > 0 && isEles) {
for (var i = 0; i < props.length; i++) {
var prop = props[i];
var _name = prop.name;
var end = prop;
var start = ani_p.startStyle[_name];
var propSpec = style.properties[start.name];
var easedVal = ease(start, end, percent, easing, propSpec);
style.overrideBypass(self, _name, easedVal);
} // for props
self.emit('style');
} // if
}
ani_p.progress = percent;
return percent;
}
function valid(start, end) {
if (start == null || end == null) {
return false;
}
if (is.number(start) && is.number(end)) {
return true;
} else if (start && end) {
return true;
}
return false;
}
module.exports = step;
/***/ }),
/* 74 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var generateCubicBezier = __webpack_require__(75);
var generateSpringRK4 = __webpack_require__(76);
var cubicBezier = function cubicBezier(t1, p1, t2, p2) {
var bezier = generateCubicBezier(t1, p1, t2, p2);
return function (start, end, percent) {
return start + (end - start) * bezier(percent);
};
};
var easings = {
'linear': function linear(start, end, percent) {
return start + (end - start) * percent;
},
// default easings
'ease': cubicBezier(0.25, 0.1, 0.25, 1),
'ease-in': cubicBezier(0.42, 0, 1, 1),
'ease-out': cubicBezier(0, 0, 0.58, 1),
'ease-in-out': cubicBezier(0.42, 0, 0.58, 1),
// sine
'ease-in-sine': cubicBezier(0.47, 0, 0.745, 0.715),
'ease-out-sine': cubicBezier(0.39, 0.575, 0.565, 1),
'ease-in-out-sine': cubicBezier(0.445, 0.05, 0.55, 0.95),
// quad
'ease-in-quad': cubicBezier(0.55, 0.085, 0.68, 0.53),
'ease-out-quad': cubicBezier(0.25, 0.46, 0.45, 0.94),
'ease-in-out-quad': cubicBezier(0.455, 0.03, 0.515, 0.955),
// cubic
'ease-in-cubic': cubicBezier(0.55, 0.055, 0.675, 0.19),
'ease-out-cubic': cubicBezier(0.215, 0.61, 0.355, 1),
'ease-in-out-cubic': cubicBezier(0.645, 0.045, 0.355, 1),
// quart
'ease-in-quart': cubicBezier(0.895, 0.03, 0.685, 0.22),
'ease-out-quart': cubicBezier(0.165, 0.84, 0.44, 1),
'ease-in-out-quart': cubicBezier(0.77, 0, 0.175, 1),
// quint
'ease-in-quint': cubicBezier(0.755, 0.05, 0.855, 0.06),
'ease-out-quint': cubicBezier(0.23, 1, 0.32, 1),
'ease-in-out-quint': cubicBezier(0.86, 0, 0.07, 1),
// expo
'ease-in-expo': cubicBezier(0.95, 0.05, 0.795, 0.035),
'ease-out-expo': cubicBezier(0.19, 1, 0.22, 1),
'ease-in-out-expo': cubicBezier(1, 0, 0, 1),
// circ
'ease-in-circ': cubicBezier(0.6, 0.04, 0.98, 0.335),
'ease-out-circ': cubicBezier(0.075, 0.82, 0.165, 1),
'ease-in-out-circ': cubicBezier(0.785, 0.135, 0.15, 0.86),
// user param easings...
'spring': function spring(tension, friction, duration) {
if (duration === 0) {
// can't get a spring w/ duration 0
return easings.linear; // duration 0 => jump to end so impl doesn't matter
}
var spring = generateSpringRK4(tension, friction, duration);
return function (start, end, percent) {
return start + (end - start) * spring(percent);
};
},
'cubic-bezier': cubicBezier
};
module.exports = easings;
/***/ }),
/* 75 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* global Float32Array */
/*! Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
function generateCubicBezier(mX1, mY1, mX2, mY2) {
var NEWTON_ITERATIONS = 4,
NEWTON_MIN_SLOPE = 0.001,
SUBDIVISION_PRECISION = 0.0000001,
SUBDIVISION_MAX_ITERATIONS = 10,
kSplineTableSize = 11,
kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
float32ArraySupported = typeof Float32Array !== 'undefined';
/* Must contain four arguments. */
if (arguments.length !== 4) {
return false;
}
/* Arguments must be numbers. */
for (var i = 0; i < 4; ++i) {
if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
return false;
}
}
/* X values must be in the [0, 1] range. */
mX1 = Math.min(mX1, 1);
mX2 = Math.min(mX2, 1);
mX1 = Math.max(mX1, 0);
mX2 = Math.max(mX2, 0);
var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
function A(aA1, aA2) {
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
}
function B(aA1, aA2) {
return 3.0 * aA2 - 6.0 * aA1;
}
function C(aA1) {
return 3.0 * aA1;
}
function calcBezier(aT, aA1, aA2) {
return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
}
function getSlope(aT, aA1, aA2) {
return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
}
function newtonRaphsonIterate(aX, aGuessT) {
for (var _i = 0; _i < NEWTON_ITERATIONS; ++_i) {
var currentSlope = getSlope(aGuessT, mX1, mX2);
if (currentSlope === 0.0) {
return aGuessT;
}
var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
aGuessT -= currentX / currentSlope;
}
return aGuessT;
}
function calcSampleValues() {
for (var _i2 = 0; _i2 < kSplineTableSize; ++_i2) {
mSampleValues[_i2] = calcBezier(_i2 * kSampleStepSize, mX1, mX2);
}
}
function binarySubdivide(aX, aA, aB) {
var currentX = void 0,
currentT = void 0,
i = 0;
do {
currentT = aA + (aB - aA) / 2.0;
currentX = calcBezier(currentT, mX1, mX2) - aX;
if (currentX > 0.0) {
aB = currentT;
} else {
aA = currentT;
}
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
return currentT;
}
function getTForX(aX) {
var intervalStart = 0.0,
currentSample = 1,
lastSample = kSplineTableSize - 1;
for (; currentSample !== lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
intervalStart += kSampleStepSize;
}
--currentSample;
var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample + 1] - mSampleValues[currentSample]),
guessForT = intervalStart + dist * kSampleStepSize,
initialSlope = getSlope(guessForT, mX1, mX2);
if (initialSlope >= NEWTON_MIN_SLOPE) {
return newtonRaphsonIterate(aX, guessForT);
} else if (initialSlope === 0.0) {
return guessForT;
} else {
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
}
}
var _precomputed = false;
function precompute() {
_precomputed = true;
if (mX1 !== mY1 || mX2 !== mY2) {
calcSampleValues();
}
}
var f = function f(aX) {
if (!_precomputed) {
precompute();
}
if (mX1 === mY1 && mX2 === mY2) {
return aX;
}
if (aX === 0) {
return 0;
}
if (aX === 1) {
return 1;
}
return calcBezier(getTForX(aX), mY1, mY2);
};
f.getControlPoints = function () {
return [{
x: mX1,
y: mY1
}, {
x: mX2,
y: mY2
}];
};
var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
f.toString = function () {
return str;
};
return f;
}
module.exports = generateCubicBezier;
/***/ }),
/* 76 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass
then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
var generateSpringRK4 = function () {
function springAccelerationForState(state) {
return -state.tension * state.x - state.friction * state.v;
}
function springEvaluateStateWithDerivative(initialState, dt, derivative) {
var state = {
x: initialState.x + derivative.dx * dt,
v: initialState.v + derivative.dv * dt,
tension: initialState.tension,
friction: initialState.friction
};
return { dx: state.v, dv: springAccelerationForState(state) };
}
function springIntegrateState(state, dt) {
var a = {
dx: state.v,
dv: springAccelerationForState(state)
},
b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
d = springEvaluateStateWithDerivative(state, dt, c),
dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);
state.x = state.x + dxdt * dt;
state.v = state.v + dvdt * dt;
return state;
}
return function springRK4Factory(tension, friction, duration) {
var initState = {
x: -1,
v: 0,
tension: null,
friction: null
},
path = [0],
time_lapsed = 0,
tolerance = 1 / 10000,
DT = 16 / 1000,
have_duration = void 0,
dt = void 0,
last_state = void 0;
tension = parseFloat(tension) || 500;
friction = parseFloat(friction) || 20;
duration = duration || null;
initState.tension = tension;
initState.friction = friction;
have_duration = duration !== null;
/* Calculate the actual time it takes for this animation to complete with the provided conditions. */
if (have_duration) {
/* Run the simulation without a duration. */
time_lapsed = springRK4Factory(tension, friction);
/* Compute the adjusted time delta. */
dt = time_lapsed / duration * DT;
} else {
dt = DT;
}
for (;;) {
/* Next/step function .*/
last_state = springIntegrateState(last_state || initState, dt);
/* Store the position. */
path.push(1 + last_state.x);
time_lapsed += 16;
/* If the change threshold is reached, break. */
if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
break;
}
}
/* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
computed path and returns a snapshot of the position according to a given percentComplete. */
return !have_duration ? time_lapsed : function (percentComplete) {
return path[percentComplete * (path.length - 1) | 0];
};
};
}();
module.exports = generateSpringRK4;
/***/ }),
/* 77 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
function getEasedValue(type, start, end, percent, easingFn) {
if (percent === 1) {
return end;
}
var val = easingFn(start, end, percent);
if (type == null) {
return val;
}
if (type.roundValue || type.color) {
val = Math.round(val);
}
if (type.min !== undefined) {
val = Math.max(val, type.min);
}
if (type.max !== undefined) {
val = Math.min(val, type.max);
}
return val;
}
function getValue(prop, spec) {
if (prop.pfValue != null || prop.value != null) {
if (prop.pfValue != null && (spec == null || spec.type.units !== '%')) {
return prop.pfValue;
} else {
return prop.value;
}
} else {
return prop;
}
}
function ease(startProp, endProp, percent, easingFn, propSpec) {
var type = propSpec != null ? propSpec.type : null;
if (percent < 0) {
percent = 0;
} else if (percent > 1) {
percent = 1;
}
var start = getValue(startProp, propSpec);
var end = getValue(endProp, propSpec);
if (is.number(start) && is.number(end)) {
return getEasedValue(type, start, end, percent, easingFn);
} else if (is.array(start) && is.array(end)) {
var easedArr = [];
for (var i = 0; i < end.length; i++) {
var si = start[i];
var ei = end[i];
if (si != null && ei != null) {
var val = getEasedValue(type, si, ei, percent, easingFn);
easedArr.push(val);
} else {
easedArr.push(ei);
}
}
return easedArr;
}
return undefined;
}
module.exports = ease;
/***/ }),
/* 78 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function startAnimation(self, ani, now, isCore) {
var isEles = !isCore;
var ele = self;
var ani_p = ani._private;
var cy = isCore ? self : self.cy();
var style = cy.style();
if (isEles) {
var pos = ele.position();
ani_p.startPosition = ani_p.startPosition || {
x: pos.x,
y: pos.y
};
ani_p.startStyle = ani_p.startStyle || style.getAnimationStartStyle(ele, ani_p.style);
}
if (isCore) {
var pan = cy._private.pan;
ani_p.startPan = ani_p.startPan || {
x: pan.x,
y: pan.y
};
ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom;
}
ani_p.started = true;
ani_p.startTime = now - ani_p.progress * ani_p.duration;
}
module.exports = startAnimation;
/***/ }),
/* 79 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var Emitter = __webpack_require__(11);
var define = __webpack_require__(4);
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Selector = __webpack_require__(6);
var emitterOptions = {
qualifierCompare: function qualifierCompare(selector1, selector2) {
if (selector1 == null || selector2 == null) {
return selector1 == null && selector2 == null;
} else {
return selector1.sameText(selector2);
}
},
eventMatches: function eventMatches(cy, listener, eventObj) {
var selector = listener.qualifier;
if (selector != null) {
return cy !== eventObj.target && is.element(eventObj.target) && selector.matches(eventObj.target);
}
return true;
},
eventFields: function eventFields(cy) {
return {
cy: cy,
target: cy
};
},
callbackContext: function callbackContext(cy, listener, eventObj) {
return listener.qualifier != null ? eventObj.target : cy;
}
};
var argSelector = function argSelector(arg) {
if (is.string(arg)) {
return new Selector(arg);
} else {
return arg;
}
};
var elesfn = {
createEmitter: function createEmitter() {
var _p = this._private;
if (!_p.emitter) {
_p.emitter = new Emitter(util.assign({
context: this
}, emitterOptions));
}
return this;
},
emitter: function emitter() {
return this._private.emitter;
},
on: function on(events, selector, callback) {
this.emitter().on(events, argSelector(selector), callback);
return this;
},
removeListener: function removeListener(events, selector, callback) {
this.emitter().removeListener(events, argSelector(selector), callback);
return this;
},
one: function one(events, selector, callback) {
this.emitter().one(events, argSelector(selector), callback);
return this;
},
once: function once(events, selector, callback) {
this.emitter().one(events, argSelector(selector), callback);
return this;
},
emit: function emit(events, extraParams) {
this.emitter().emit(events, extraParams);
return this;
}
};
define.eventAliasesOn(elesfn);
module.exports = elesfn;
/***/ }),
/* 80 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var corefn = {
png: function png(options) {
var renderer = this._private.renderer;
options = options || {};
return renderer.png(options);
},
jpg: function jpg(options) {
var renderer = this._private.renderer;
options = options || {};
options.bg = options.bg || '#fff';
return renderer.jpg(options);
}
};
corefn.jpeg = corefn.jpg;
module.exports = corefn;
/***/ }),
/* 81 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var corefn = {
layout: function layout(options) {
var cy = this;
if (options == null) {
util.error('Layout options must be specified to make a layout');
return;
}
if (options.name == null) {
util.error('A `name` must be specified to make a layout');
return;
}
var name = options.name;
var Layout = cy.extension('layout', name);
if (Layout == null) {
util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?');
return;
}
var eles = void 0;
if (is.string(options.eles)) {
eles = cy.$(options.eles);
} else {
eles = options.eles != null ? options.eles : cy.$();
}
var layout = new Layout(util.extend({}, options, {
cy: cy,
eles: eles
}));
return layout;
}
};
corefn.createLayout = corefn.makeLayout = corefn.layout;
module.exports = corefn;
/***/ }),
/* 82 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var corefn = {
notify: function notify(params) {
var _p = this._private;
if (_p.batchingNotify) {
var bEles = _p.batchNotifyEles;
var bTypes = _p.batchNotifyTypes;
if (params.eles) {
bEles.merge(params.eles);
}
if (!bTypes.ids[params.type]) {
bTypes.push(params.type);
bTypes.ids[params.type] = true;
}
return; // notifications are disabled during batching
}
if (!_p.notificationsEnabled) {
return;
} // exit on disabled
var renderer = this.renderer();
// exit if destroy() called on core or renderer in between frames #1499 #1528
if (this.isDestroyed() || !renderer) {
return;
}
renderer.notify(params);
},
notifications: function notifications(bool) {
var p = this._private;
if (bool === undefined) {
return p.notificationsEnabled;
} else {
p.notificationsEnabled = bool ? true : false;
}
},
noNotifications: function noNotifications(callback) {
this.notifications(false);
callback();
this.notifications(true);
},
batching: function batching() {
return this._private.batchCount > 0;
},
startBatch: function startBatch() {
var _p = this._private;
if (_p.batchCount == null) {
_p.batchCount = 0;
}
if (_p.batchCount === 0) {
_p.batchingStyle = _p.batchingNotify = true;
_p.batchStyleEles = this.collection();
_p.batchNotifyEles = this.collection();
_p.batchNotifyTypes = [];
_p.batchNotifyTypes.ids = {};
}
_p.batchCount++;
return this;
},
endBatch: function endBatch() {
var _p = this._private;
_p.batchCount--;
if (_p.batchCount === 0) {
// update style for dirty eles
_p.batchingStyle = false;
_p.batchStyleEles.updateStyle();
// notify the renderer of queued eles and event types
_p.batchingNotify = false;
this.notify({
type: _p.batchNotifyTypes,
eles: _p.batchNotifyEles
});
}
return this;
},
batch: function batch(callback) {
this.startBatch();
callback();
this.endBatch();
return this;
},
// for backwards compatibility
batchData: function batchData(map) {
var cy = this;
return this.batch(function () {
var ids = Object.keys(map);
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var data = map[id];
var ele = cy.getElementById(id);
ele.data(data);
}
});
}
};
module.exports = corefn;
/***/ }),
/* 83 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var corefn = {
renderTo: function renderTo(context, zoom, pan, pxRatio) {
var r = this._private.renderer;
r.renderTo(context, zoom, pan, pxRatio);
return this;
},
renderer: function renderer() {
return this._private.renderer;
},
forceRender: function forceRender() {
this.notify({
type: 'draw'
});
return this;
},
resize: function resize() {
this.invalidateSize();
this.notify({
type: 'resize'
});
this.emit('resize');
return this;
},
initRenderer: function initRenderer(options) {
var cy = this;
var RendererProto = cy.extension('renderer', options.name);
if (RendererProto == null) {
util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name);
return;
}
cy._private.renderer = new RendererProto(util.extend({}, options, { cy: cy }));
this.notify({ type: 'init' });
},
destroyRenderer: function destroyRenderer() {
var cy = this;
cy.notify({ type: 'destroy' }); // destroy the renderer
var domEle = cy.container();
if (domEle) {
domEle._cyreg = null;
while (domEle.childNodes.length > 0) {
domEle.removeChild(domEle.childNodes[0]);
}
}
cy._private.renderer = null; // to be extra safe, remove the ref
},
onRender: function onRender(fn) {
return this.on('render', fn);
},
offRender: function offRender(fn) {
return this.off('render', fn);
}
};
corefn.invalidateDimensions = corefn.resize;
module.exports = corefn;
/***/ }),
/* 84 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Collection = __webpack_require__(7);
var corefn = {
// get a collection
// - empty collection on no args
// - collection of elements in the graph on selector arg
// - guarantee a returned collection when elements or collection specified
collection: function collection(eles, opts) {
if (is.string(eles)) {
return this.$(eles);
} else if (is.elementOrCollection(eles)) {
return eles.collection();
} else if (is.array(eles)) {
return new Collection(this, eles, opts);
}
return new Collection(this);
},
nodes: function nodes(selector) {
var nodes = this.$(function (ele) {
return ele.isNode();
});
if (selector) {
return nodes.filter(selector);
}
return nodes;
},
edges: function edges(selector) {
var edges = this.$(function (ele) {
return ele.isEdge();
});
if (selector) {
return edges.filter(selector);
}
return edges;
},
// search the graph like jQuery
$: function $(selector) {
var eles = this._private.elements;
if (selector) {
return eles.filter(selector);
} else {
return eles.spawnSelf();
}
},
mutableElements: function mutableElements() {
return this._private.elements;
}
};
// aliases
corefn.elements = corefn.filter = corefn.$;
module.exports = corefn;
/***/ }),
/* 85 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var Style = __webpack_require__(18);
var corefn = {
style: function style(newStyle) {
if (newStyle) {
var s = this.setStyle(newStyle);
s.update();
}
return this._private.style;
},
setStyle: function setStyle(style) {
var _p = this._private;
if (is.stylesheet(style)) {
_p.style = style.generateStyle(this);
} else if (is.array(style)) {
_p.style = Style.fromJson(this, style);
} else if (is.string(style)) {
_p.style = Style.fromString(this, style);
} else {
_p.style = Style(this);
}
return _p.style;
}
};
module.exports = corefn;
/***/ }),
/* 86 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var Promise = __webpack_require__(5);
var styfn = {};
// (potentially expensive calculation)
// apply the style to the element based on
// - its bypass
// - what selectors match it
styfn.apply = function (eles) {
var self = this;
var _p = self._private;
var cy = _p.cy;
var updatedEles = cy.collection();
if (_p.newStyle) {
// clear style caches
_p.contextStyles = {};
_p.propDiffs = {};
self.cleanElements(eles, true);
}
for (var ie = 0; ie < eles.length; ie++) {
var ele = eles[ie];
var cxtMeta = self.getContextMeta(ele);
if (cxtMeta.empty) {
continue;
} else {
updatedEles.merge(ele);
}
var cxtStyle = self.getContextStyle(cxtMeta);
var app = self.applyContextStyle(cxtMeta, cxtStyle, ele);
if (!_p.newStyle) {
self.updateTransitions(ele, app.diffProps);
}
self.updateStyleHints(ele);
} // for elements
_p.newStyle = false;
return updatedEles;
};
styfn.getPropertiesDiff = function (oldCxtKey, newCxtKey) {
var self = this;
var cache = self._private.propDiffs = self._private.propDiffs || {};
var dualCxtKey = oldCxtKey + '-' + newCxtKey;
var cachedVal = cache[dualCxtKey];
if (cachedVal) {
return cachedVal;
}
var diffProps = [];
var addedProp = {};
for (var i = 0; i < self.length; i++) {
var cxt = self[i];
var oldHasCxt = oldCxtKey[i] === 't';
var newHasCxt = newCxtKey[i] === 't';
var cxtHasDiffed = oldHasCxt !== newHasCxt;
var cxtHasMappedProps = cxt.mappedProperties.length > 0;
if (cxtHasDiffed || cxtHasMappedProps) {
var props = void 0;
if (cxtHasDiffed && cxtHasMappedProps) {
props = cxt.properties; // suffices b/c mappedProperties is a subset of properties
} else if (cxtHasDiffed) {
props = cxt.properties; // need to check them all
} else if (cxtHasMappedProps) {
props = cxt.mappedProperties; // only need to check mapped
}
for (var j = 0; j < props.length; j++) {
var prop = props[j];
var name = prop.name;
// if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter
// (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result
// is cached)
var laterCxtOverrides = false;
for (var k = i + 1; k < self.length; k++) {
var laterCxt = self[k];
var hasLaterCxt = newCxtKey[k] === 't';
if (!hasLaterCxt) {
continue;
} // can't override unless the context is active
laterCxtOverrides = laterCxt.properties[prop.name] != null;
if (laterCxtOverrides) {
break;
} // exit early as long as one later context overrides
}
if (!addedProp[name] && !laterCxtOverrides) {
addedProp[name] = true;
diffProps.push(name);
}
} // for props
} // if
} // for contexts
cache[dualCxtKey] = diffProps;
return diffProps;
};
styfn.getContextMeta = function (ele) {
var self = this;
var cxtKey = '';
var diffProps = void 0;
var prevKey = ele._private.styleCxtKey || '';
if (self._private.newStyle) {
prevKey = ''; // since we need to apply all style if a fresh stylesheet
}
// get the cxt key
for (var i = 0; i < self.length; i++) {
var context = self[i];
var contextSelectorMatches = context.selector && context.selector.matches(ele); // NB: context.selector may be null for 'core'
if (contextSelectorMatches) {
cxtKey += 't';
} else {
cxtKey += 'f';
}
} // for context
diffProps = self.getPropertiesDiff(prevKey, cxtKey);
ele._private.styleCxtKey = cxtKey;
return {
key: cxtKey,
diffPropNames: diffProps,
empty: diffProps.length === 0
};
};
// gets a computed ele style object based on matched contexts
styfn.getContextStyle = function (cxtMeta) {
var cxtKey = cxtMeta.key;
var self = this;
var cxtStyles = this._private.contextStyles = this._private.contextStyles || {};
// if already computed style, returned cached copy
if (cxtStyles[cxtKey]) {
return cxtStyles[cxtKey];
}
var style = {
_private: {
key: cxtKey
}
};
for (var i = 0; i < self.length; i++) {
var cxt = self[i];
var hasCxt = cxtKey[i] === 't';
if (!hasCxt) {
continue;
}
for (var j = 0; j < cxt.properties.length; j++) {
var prop = cxt.properties[j];
style[prop.name] = prop;
}
}
cxtStyles[cxtKey] = style;
return style;
};
styfn.applyContextStyle = function (cxtMeta, cxtStyle, ele) {
var self = this;
var diffProps = cxtMeta.diffPropNames;
var retDiffProps = {};
for (var i = 0; i < diffProps.length; i++) {
var diffPropName = diffProps[i];
var cxtProp = cxtStyle[diffPropName];
var eleProp = ele.pstyle(diffPropName);
if (!cxtProp) {
// no context prop means delete
if (!eleProp) {
continue; // no existing prop means nothing needs to be removed
// nb affects initial application on mapped values like control-point-distances
} else if (eleProp.bypass) {
cxtProp = { name: diffPropName, deleteBypassed: true };
} else {
cxtProp = { name: diffPropName, delete: true };
}
}
// save cycles when the context prop doesn't need to be applied
if (eleProp === cxtProp) {
continue;
}
var retDiffProp = retDiffProps[diffPropName] = {
prev: eleProp
};
self.applyParsedProperty(ele, cxtProp);
retDiffProp.next = ele.pstyle(diffPropName);
if (retDiffProp.next && retDiffProp.next.bypass) {
retDiffProp.next = retDiffProp.next.bypassed;
}
}
return {
diffProps: retDiffProps
};
};
styfn.updateStyleHints = function (ele) {
var _p = ele._private;
var self = this;
if (ele.removed()) {
return;
}
// set whether has pie or not; for greater efficiency
var hasPie = false;
if (_p.group === 'nodes') {
for (var i = 1; i <= self.pieBackgroundN; i++) {
// 1..N
var _size = ele.pstyle('pie-' + i + '-background-size').value;
if (_size > 0) {
hasPie = true;
break;
}
}
}
_p.hasPie = hasPie;
var transform = ele.pstyle('text-transform').strValue;
var content = ele.pstyle('label').strValue;
var srcContent = ele.pstyle('source-label').strValue;
var tgtContent = ele.pstyle('target-label').strValue;
var fStyle = ele.pstyle('font-style').strValue;
var size = ele.pstyle('font-size').pfValue + 'px';
var family = ele.pstyle('font-family').strValue;
// let letiant = style['font-letiant'].strValue;
var weight = ele.pstyle('font-weight').strValue;
var valign = ele.pstyle('text-valign').strValue;
var halign = ele.pstyle('text-valign').strValue;
var oWidth = ele.pstyle('text-outline-width').pfValue;
var wrap = ele.pstyle('text-wrap').strValue;
var wrapW = ele.pstyle('text-max-width').pfValue;
var labelStyleKey = fStyle + '$' + size + '$' + family + '$' + weight + '$' + transform + '$' + valign + '$' + halign + '$' + oWidth + '$' + wrap + '$' + wrapW;
_p.labelStyleKey = labelStyleKey;
_p.sourceLabelKey = labelStyleKey + '$' + srcContent;
_p.targetLabelKey = labelStyleKey + '$' + tgtContent;
_p.labelKey = labelStyleKey + '$' + content;
_p.fontKey = fStyle + '$' + weight + '$' + size + '$' + family;
_p.styleKey = Date.now();
};
// apply a property to the style (for internal use)
// returns whether application was successful
//
// now, this function flattens the property, and here's how:
//
// for parsedProp:{ bypass: true, deleteBypass: true }
// no property is generated, instead the bypass property in the
// element's style is replaced by what's pointed to by the `bypassed`
// field in the bypass property (i.e. restoring the property the
// bypass was overriding)
//
// for parsedProp:{ mapped: truthy }
// the generated flattenedProp:{ mapping: prop }
//
// for parsedProp:{ bypass: true }
// the generated flattenedProp:{ bypassed: parsedProp }
styfn.applyParsedProperty = function (ele, parsedProp) {
var self = this;
var prop = parsedProp;
var style = ele._private.style;
var fieldVal = void 0,
flatProp = void 0;
var types = self.types;
var type = self.properties[prop.name].type;
var propIsBypass = prop.bypass;
var origProp = style[prop.name];
var origPropIsBypass = origProp && origProp.bypass;
var _p = ele._private;
var flatPropMapping = 'mapping';
var checkZOrder = function checkZOrder() {
self.checkZOrderTrigger(ele, prop.name, origProp ? origProp.value : null, prop.value);
};
// edges connected to compound nodes can not be haystacks
if (parsedProp.name === 'curve-style' && parsedProp.value === 'haystack' && ele.isEdge() && (ele.isLoop() || ele.source().isParent() || ele.target().isParent())) {
prop = parsedProp = this.parse(parsedProp.name, 'bezier', propIsBypass);
}
if (prop.delete) {
// delete the property and use the default value on falsey value
style[prop.name] = undefined;
checkZOrder();
return true;
}
if (prop.deleteBypassed) {
// delete the property that the
if (!origProp) {
checkZOrder();
return true; // can't delete if no prop
} else if (origProp.bypass) {
// delete bypassed
origProp.bypassed = undefined;
checkZOrder();
return true;
} else {
return false; // we're unsuccessful deleting the bypassed
}
}
// check if we need to delete the current bypass
if (prop.deleteBypass) {
// then this property is just here to indicate we need to delete
if (!origProp) {
checkZOrder();
return true; // property is already not defined
} else if (origProp.bypass) {
// then replace the bypass property with the original
// because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)
style[prop.name] = origProp.bypassed;
checkZOrder();
return true;
} else {
return false; // we're unsuccessful deleting the bypass
}
}
var printMappingErr = function printMappingErr() {
util.error('Do not assign mappings to elements without corresponding data (e.g. ele `' + ele.id() + '` for property `' + prop.name + '` with data field `' + prop.field + '`); try a `[' + prop.field + ']` selector to limit scope to elements with `' + prop.field + '` defined');
};
// put the property in the style objects
switch (prop.mapped) {// flatten the property if mapped
case types.mapData:
{
// flatten the field (e.g. data.foo.bar)
var fields = prop.field.split('.');
var _fieldVal = _p.data;
for (var i = 0; i < fields.length && _fieldVal; i++) {
var field = fields[i];
_fieldVal = _fieldVal[field];
}
var percent = void 0;
if (!is.number(_fieldVal)) {
// then keep the mapping but assume 0% for now
percent = 0;
} else {
percent = (_fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin);
}
// make sure to bound percent value
if (percent < 0) {
percent = 0;
} else if (percent > 1) {
percent = 1;
}
if (type.color) {
var r1 = prop.valueMin[0];
var r2 = prop.valueMax[0];
var g1 = prop.valueMin[1];
var g2 = prop.valueMax[1];
var b1 = prop.valueMin[2];
var b2 = prop.valueMax[2];
var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];
var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];
var clr = [Math.round(r1 + (r2 - r1) * percent), Math.round(g1 + (g2 - g1) * percent), Math.round(b1 + (b2 - b1) * percent), Math.round(a1 + (a2 - a1) * percent)];
flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing
bypass: prop.bypass, // we're a bypass if the mapping property is a bypass
name: prop.name,
value: clr,
strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'
};
} else if (type.number) {
var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;
flatProp = this.parse(prop.name, calcValue, prop.bypass, flatPropMapping);
} else {
return false; // can only map to colours and numbers
}
if (!flatProp) {
// if we can't flatten the property, then use the origProp so we still keep the mapping itself
flatProp = this.parse(prop.name, origProp.strValue, prop.bypass, flatPropMapping);
}
if (!flatProp) {
printMappingErr();
}
flatProp.mapping = prop; // keep a reference to the mapping
prop = flatProp; // the flattened (mapped) property is the one we want
break;
}
// direct mapping
case types.data:
{
// flatten the field (e.g. data.foo.bar)
var _fields = prop.field.split('.');
var _fieldVal2 = _p.data;
if (_fieldVal2) {
for (var _i = 0; _i < _fields.length; _i++) {
var _field = _fields[_i];
_fieldVal2 = _fieldVal2[_field];
}
}
flatProp = this.parse(prop.name, _fieldVal2, prop.bypass, flatPropMapping);
if (!flatProp) {
// if we can't flatten the property, then use the origProp so we still keep the mapping itself
var flatPropVal = origProp ? origProp.strValue : '';
flatProp = this.parse(prop.name, flatPropVal, prop.bypass, flatPropMapping);
}
if (!flatProp) {
printMappingErr();
}
flatProp.mapping = prop; // keep a reference to the mapping
prop = flatProp; // the flattened (mapped) property is the one we want
break;
}
case types.fn:
{
var fn = prop.value;
var fnRetVal = fn(ele);
flatProp = this.parse(prop.name, fnRetVal, prop.bypass, flatPropMapping);
flatProp.mapping = prop; // keep a reference to the mapping
prop = flatProp; // the flattened (mapped) property is the one we want
break;
}
case undefined:
break; // just set the property
default:
return false; // not a valid mapping
}
// if the property is a bypass property, then link the resultant property to the original one
if (propIsBypass) {
if (origPropIsBypass) {
// then this bypass overrides the existing one
prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass
} else {
// then link the orig prop to the new bypass
prop.bypassed = origProp;
}
style[prop.name] = prop; // and set
} else {
// prop is not bypass
if (origPropIsBypass) {
// then keep the orig prop (since it's a bypass) and link to the new prop
origProp.bypassed = prop;
} else {
// then just replace the old prop with the new one
style[prop.name] = prop;
}
}
checkZOrder();
return true;
};
styfn.cleanElements = function (eles, keepBypasses) {
var self = this;
var props = self.properties;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (!keepBypasses) {
ele._private.style = {};
} else {
var style = ele._private.style;
for (var j = 0; j < props.length; j++) {
var prop = props[j];
var eleProp = style[prop.name];
if (eleProp) {
if (eleProp.bypass) {
eleProp.bypassed = null;
} else {
style[prop.name] = null;
}
}
}
}
}
};
// updates the visual style for all elements (useful for manual style modification after init)
styfn.update = function () {
var cy = this._private.cy;
var eles = cy.mutableElements();
eles.updateStyle();
};
// just update the functional properties (i.e. mappings) in the elements'
// styles (less expensive than recalculation)
styfn.updateMappers = function (eles) {
var self = this;
var cy = this._private.cy;
var updatedEles = cy.collection();
for (var i = 0; i < eles.length; i++) {
// for each ele
var ele = eles[i];
var style = ele._private.style;
var updatedEle = false;
for (var j = 0; j < self.properties.length; j++) {
// for each prop
var prop = self.properties[j];
var propInStyle = style[prop.name];
if (propInStyle && propInStyle.mapping) {
var mapping = propInStyle.mapping;
this.applyParsedProperty(ele, mapping); // reapply the mapping property
updatedEle = true;
}
}
if (updatedEle) {
this.updateStyleHints(ele);
updatedEles.merge(ele);
}
}
return updatedEles;
};
// diffProps : { name => { prev, next } }
styfn.updateTransitions = function (ele, diffProps, isBypass) {
var self = this;
var _p = ele._private;
var props = ele.pstyle('transition-property').value;
var duration = ele.pstyle('transition-duration').pfValue;
var delay = ele.pstyle('transition-delay').pfValue;
if (props.length > 0 && duration > 0) {
var style = {};
// build up the style to animate towards
var anyPrev = false;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
var styProp = ele.pstyle(prop);
var diffProp = diffProps[prop];
if (!diffProp) {
continue;
}
var prevProp = diffProp.prev;
var fromProp = prevProp;
var toProp = diffProp.next != null ? diffProp.next : styProp;
var diff = false;
var initVal = void 0;
var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)
if (!fromProp) {
continue;
}
// consider px values
if (is.number(fromProp.pfValue) && is.number(toProp.pfValue)) {
diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy
initVal = fromProp.pfValue + initDt * diff;
// consider numerical values
} else if (is.number(fromProp.value) && is.number(toProp.value)) {
diff = toProp.value - fromProp.value; // nonzero is truthy
initVal = fromProp.value + initDt * diff;
// consider colour values
} else if (is.array(fromProp.value) && is.array(toProp.value)) {
diff = fromProp.value[0] !== toProp.value[0] || fromProp.value[1] !== toProp.value[1] || fromProp.value[2] !== toProp.value[2];
initVal = fromProp.strValue;
}
// the previous value is good for an animation only if it's different
if (diff) {
style[prop] = toProp.strValue; // to val
this.applyBypass(ele, prop, initVal); // from val
anyPrev = true;
}
} // end if props allow ani
// can't transition if there's nothing previous to transition from
if (!anyPrev) {
return;
}
_p.transitioning = true;
new Promise(function (resolve) {
if (delay > 0) {
ele.delayAnimation(delay).play().promise().then(resolve);
} else {
resolve();
}
}).then(function () {
return ele.animation({
style: style,
duration: duration,
easing: ele.pstyle('transition-timing-function').value,
queue: false
}).play().promise();
}).then(function () {
// if( !isBypass ){
self.removeBypasses(ele, props);
ele.emitAndNotify('style');
// }
_p.transitioning = false;
});
} else if (_p.transitioning) {
this.removeBypasses(ele, props);
ele.emitAndNotify('style');
_p.transitioning = false;
}
};
styfn.checkZOrderTrigger = function (ele, name, fromValue, toValue) {
var prop = this.properties[name];
if (prop.triggersZOrder != null && (fromValue == null || prop.triggersZOrder(fromValue, toValue))) {
this._private.cy.notify({
type: 'zorder',
eles: ele
});
}
};
module.exports = styfn;
/***/ }),
/* 87 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var styfn = {};
// bypasses are applied to an existing style on an element, and just tacked on temporarily
// returns true iff application was successful for at least 1 specified property
styfn.applyBypass = function (eles, name, value, updateTransitions) {
var self = this;
var props = [];
var isBypass = true;
// put all the properties (can specify one or many) in an array after parsing them
if (name === '*' || name === '**') {
// apply to all property names
if (value !== undefined) {
for (var i = 0; i < self.properties.length; i++) {
var prop = self.properties[i];
var _name = prop.name;
var parsedProp = this.parse(_name, value, true);
if (parsedProp) {
props.push(parsedProp);
}
}
}
} else if (is.string(name)) {
// then parse the single property
var _parsedProp = this.parse(name, value, true);
if (_parsedProp) {
props.push(_parsedProp);
}
} else if (is.plainObject(name)) {
// then parse each property
var specifiedProps = name;
updateTransitions = value;
var names = Object.keys(specifiedProps);
for (var _i = 0; _i < names.length; _i++) {
var _name2 = names[_i];
var _prop = self.properties[_name2];
var _value = specifiedProps[_name2];
if (_value === undefined) {
// try camel case name too
_value = specifiedProps[util.dash2camel(_name2)];
}
if (_value !== undefined) {
var _parsedProp2 = this.parse(_name2, _value, true);
if (_parsedProp2) {
props.push(_parsedProp2);
}
}
}
} else {
// can't do anything without well defined properties
return false;
}
// we've failed if there are no valid properties
if (props.length === 0) {
return false;
}
// now, apply the bypass properties on the elements
var ret = false; // return true if at least one succesful bypass applied
for (var _i2 = 0; _i2 < eles.length; _i2++) {
// for each ele
var ele = eles[_i2];
var diffProps = {};
var diffProp = void 0;
for (var j = 0; j < props.length; j++) {
// for each prop
var _prop2 = props[j];
if (updateTransitions) {
var prevProp = ele.pstyle(_prop2.name);
diffProp = diffProps[_prop2.name] = { prev: prevProp };
}
ret = this.applyParsedProperty(ele, _prop2) || ret;
if (updateTransitions) {
diffProp.next = ele.pstyle(_prop2.name);
}
} // for props
if (ret) {
this.updateStyleHints(ele);
}
if (updateTransitions) {
this.updateTransitions(ele, diffProps, isBypass);
}
} // for eles
return ret;
};
// only useful in specific cases like animation
styfn.overrideBypass = function (eles, name, value) {
name = util.camel2dash(name);
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var prop = ele._private.style[name];
var type = this.properties[name].type;
var isColor = type.color;
var isMulti = type.mutiple;
if (!prop || !prop.bypass) {
// need a bypass if one doesn't exist
this.applyBypass(ele, name, value);
continue;
}
var oldValue = prop.pfValue != null ? prop.pfValue : prop.value;
prop.value = value;
if (prop.pfValue != null) {
prop.pfValue = value;
}
if (isColor) {
prop.strValue = 'rgb(' + value.join(',') + ')';
} else if (isMulti) {
prop.strValue = value.join(' ');
} else {
prop.strValue = '' + value;
}
this.checkZOrderTrigger(ele, name, oldValue, value);
}
};
styfn.removeAllBypasses = function (eles, updateTransitions) {
return this.removeBypasses(eles, this.propertyNames, updateTransitions);
};
styfn.removeBypasses = function (eles, props, updateTransitions) {
var isBypass = true;
for (var j = 0; j < eles.length; j++) {
var ele = eles[j];
var diffProps = {};
for (var i = 0; i < props.length; i++) {
var name = props[i];
var prop = this.properties[name];
var prevProp = ele.pstyle(prop.name);
if (!prevProp || !prevProp.bypass) {
// if a bypass doesn't exist for the prop, nothing needs to be removed
continue;
}
var value = ''; // empty => remove bypass
var parsedProp = this.parse(name, value, true);
var diffProp = diffProps[prop.name] = { prev: prevProp };
this.applyParsedProperty(ele, parsedProp);
diffProp.next = ele.pstyle(prop.name);
} // for props
this.updateStyleHints(ele);
if (updateTransitions) {
this.updateTransitions(ele, diffProps, isBypass);
}
} // for eles
};
module.exports = styfn;
/***/ }),
/* 88 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var window = __webpack_require__(3);
var styfn = {};
// gets what an em size corresponds to in pixels relative to a dom element
styfn.getEmSizeInPixels = function () {
var px = this.containerCss('font-size');
if (px != null) {
return parseFloat(px);
} else {
return 1; // for headless
}
};
// gets css property from the core container
styfn.containerCss = function (propName) {
var cy = this._private.cy;
var domElement = cy.container();
if (window && domElement && window.getComputedStyle) {
return window.getComputedStyle(domElement).getPropertyValue(propName);
}
};
module.exports = styfn;
/***/ }),
/* 89 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var styfn = {};
// gets the rendered style for an element
styfn.getRenderedStyle = function (ele, prop) {
if (prop) {
return this.getStylePropertyValue(ele, prop, true);
} else {
return this.getRawStyle(ele, true);
}
};
// gets the raw style for an element
styfn.getRawStyle = function (ele, isRenderedVal) {
var self = this;
ele = ele[0]; // insure it's an element
if (ele) {
var rstyle = {};
for (var i = 0; i < self.properties.length; i++) {
var prop = self.properties[i];
var val = self.getStylePropertyValue(ele, prop.name, isRenderedVal);
if (val != null) {
rstyle[prop.name] = val;
rstyle[util.dash2camel(prop.name)] = val;
}
}
return rstyle;
}
};
styfn.getIndexedStyle = function (ele, property, subproperty, index) {
var pstyle = ele.pstyle(property)[subproperty][index];
return pstyle != null ? pstyle : ele.cy().style().getDefaultProperty(property)[subproperty][0];
};
styfn.getStylePropertyValue = function (ele, propName, isRenderedVal) {
var self = this;
ele = ele[0]; // insure it's an element
if (ele) {
var prop = self.properties[propName];
if (prop.alias) {
prop = prop.pointsTo;
}
var type = prop.type;
var styleProp = ele.pstyle(prop.name);
var zoom = ele.cy().zoom();
if (styleProp) {
var units = styleProp.units ? type.implicitUnits || 'px' : null;
var val = units ? [].concat(styleProp.pfValue).map(function (pfValue) {
return pfValue * (isRenderedVal ? zoom : 1) + units;
}).join(' ') : styleProp.strValue;
return val;
}
}
};
styfn.getAnimationStartStyle = function (ele, aniProps) {
var rstyle = {};
for (var i = 0; i < aniProps.length; i++) {
var aniProp = aniProps[i];
var name = aniProp.name;
var styleProp = ele.pstyle(name);
if (styleProp !== undefined) {
// then make a prop of it
if (is.plainObject(styleProp)) {
styleProp = this.parse(name, styleProp.strValue);
} else {
styleProp = this.parse(name, styleProp);
}
}
if (styleProp) {
rstyle[name] = styleProp;
}
}
return rstyle;
};
styfn.getPropsList = function (propsObj) {
var self = this;
var rstyle = [];
var style = propsObj;
var props = self.properties;
if (style) {
var names = Object.keys(style);
for (var i = 0; i < names.length; i++) {
var name = names[i];
var val = style[name];
var prop = props[name] || props[util.camel2dash(name)];
var styleProp = this.parse(prop.name, val);
if (styleProp) {
rstyle.push(styleProp);
}
}
}
return rstyle;
};
module.exports = styfn;
/***/ }),
/* 90 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var styfn = {};
styfn.appendFromJson = function (json) {
var style = this;
for (var i = 0; i < json.length; i++) {
var context = json[i];
var selector = context.selector;
var props = context.style || context.css;
var names = Object.keys(props);
style.selector(selector); // apply selector
for (var j = 0; j < names.length; j++) {
var name = names[j];
var value = props[name];
style.css(name, value); // apply property
}
}
return style;
};
// accessible cy.style() function
styfn.fromJson = function (json) {
var style = this;
style.resetToDefault();
style.appendFromJson(json);
return style;
};
// get json from cy.style() api
styfn.json = function () {
var json = [];
for (var i = this.defaultLength; i < this.length; i++) {
var cxt = this[i];
var selector = cxt.selector;
var props = cxt.properties;
var css = {};
for (var j = 0; j < props.length; j++) {
var prop = props[j];
css[prop.name] = prop.strValue;
}
json.push({
selector: !selector ? 'core' : selector.toString(),
style: css
});
}
return json;
};
module.exports = styfn;
/***/ }),
/* 91 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var Selector = __webpack_require__(6);
var styfn = {};
styfn.appendFromString = function (string) {
var self = this;
var style = this;
var remaining = '' + string;
var selAndBlockStr = void 0;
var blockRem = void 0;
var propAndValStr = void 0;
// remove comments from the style string
remaining = remaining.replace(/[/][*](\s|.)+?[*][/]/g, '');
function removeSelAndBlockFromRemaining() {
// remove the parsed selector and block from the remaining text to parse
if (remaining.length > selAndBlockStr.length) {
remaining = remaining.substr(selAndBlockStr.length);
} else {
remaining = '';
}
}
function removePropAndValFromRem() {
// remove the parsed property and value from the remaining block text to parse
if (blockRem.length > propAndValStr.length) {
blockRem = blockRem.substr(propAndValStr.length);
} else {
blockRem = '';
}
}
while (true) {
var nothingLeftToParse = remaining.match(/^\s*$/);
if (nothingLeftToParse) {
break;
}
var selAndBlock = remaining.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);
if (!selAndBlock) {
util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);
break;
}
selAndBlockStr = selAndBlock[0];
// parse the selector
var selectorStr = selAndBlock[1];
if (selectorStr !== 'core') {
var selector = new Selector(selectorStr);
if (selector._private.invalid) {
util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);
// skip this selector and block
removeSelAndBlockFromRemaining();
continue;
}
}
// parse the block of properties and values
var blockStr = selAndBlock[2];
var invalidBlock = false;
blockRem = blockStr;
var props = [];
while (true) {
var _nothingLeftToParse = blockRem.match(/^\s*$/);
if (_nothingLeftToParse) {
break;
}
var propAndVal = blockRem.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);
if (!propAndVal) {
util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);
invalidBlock = true;
break;
}
propAndValStr = propAndVal[0];
var propStr = propAndVal[1];
var valStr = propAndVal[2];
var prop = self.properties[propStr];
if (!prop) {
util.error('Skipping property: Invalid property name in: ' + propAndValStr);
// skip this property in the block
removePropAndValFromRem();
continue;
}
var parsedProp = style.parse(propStr, valStr);
if (!parsedProp) {
util.error('Skipping property: Invalid property definition in: ' + propAndValStr);
// skip this property in the block
removePropAndValFromRem();
continue;
}
props.push({
name: propStr,
val: valStr
});
removePropAndValFromRem();
}
if (invalidBlock) {
removeSelAndBlockFromRemaining();
break;
}
// put the parsed block in the style
style.selector(selectorStr);
for (var i = 0; i < props.length; i++) {
var _prop = props[i];
style.css(_prop.name, _prop.val);
}
removeSelAndBlockFromRemaining();
}
return style;
};
styfn.fromString = function (string) {
var style = this;
style.resetToDefault();
style.appendFromString(string);
return style;
};
module.exports = styfn;
/***/ }),
/* 92 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var styfn = {};
(function () {
var number = util.regex.number;
var rgba = util.regex.rgbaNoBackRefs;
var hsla = util.regex.hslaNoBackRefs;
var hex3 = util.regex.hex3;
var hex6 = util.regex.hex6;
var data = function data(prefix) {
return '^' + prefix + '\\s*\\(\\s*([\\w\\.]+)\\s*\\)$';
};
var mapData = function mapData(prefix) {
var mapArg = number + '|\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6;
return '^' + prefix + '\\s*\\(([\\w\\.]+)\\s*\\,\\s*(' + number + ')\\s*\\,\\s*(' + number + ')\\s*,\\s*(' + mapArg + ')\\s*\\,\\s*(' + mapArg + ')\\)$';
};
var urlRegexes = ['^url\\s*\\(\\s*[\'"]?(.+?)[\'"]?\\s*\\)$', '^(none)$', '^(.+)$'];
// each visual style property has a type and needs to be validated according to it
styfn.types = {
time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' },
percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' },
zeroOneNumber: { number: true, min: 0, max: 1, unitless: true },
zeroOneNumbers: { number: true, min: 0, max: 1, unitless: true, multiple: true },
nOneOneNumber: { number: true, min: -1, max: 1, unitless: true },
nonNegativeInt: { number: true, min: 0, integer: true, unitless: true },
position: { enums: ['parent', 'origin'] },
nodeSize: { number: true, min: 0, enums: ['label'] },
number: { number: true, unitless: true },
numbers: { number: true, unitless: true, multiple: true },
positiveNumber: { number: true, unitless: true, min: 0, strictMin: true },
size: { number: true, min: 0 },
bidirectionalSize: { number: true }, // allows negative
bidirectionalSizes: { number: true, multiple: true }, // allows negative
sizeMaybePercent: { number: true, min: 0, allowPercent: true },
paddingRelativeTo: { enums: ['width', 'height', 'average', 'min', 'max'] },
bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'], multiple: true },
bgPos: { number: true, allowPercent: true, multiple: true },
bgRelativeTo: { enums: ['inner', 'include-padding'], multiple: true },
bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'], multiple: true },
bgFit: { enums: ['none', 'contain', 'cover'], multiple: true },
bgCrossOrigin: { enums: ['anonymous', 'use-credentials'], multiple: true },
bgClip: { enums: ['none', 'node'] },
color: { color: true },
bool: { enums: ['yes', 'no'] },
lineStyle: { enums: ['solid', 'dotted', 'dashed'] },
borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] },
curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] },
fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' },
fontletiant: { enums: ['small-caps', 'normal'] },
fontStyle: { enums: ['italic', 'normal', 'oblique'] },
fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] },
textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] },
textTransform: { enums: ['none', 'uppercase', 'lowercase'] },
textWrap: { enums: ['none', 'wrap', 'ellipsis'] },
textBackgroundShape: { enums: ['rectangle', 'roundrectangle'] },
nodeShape: { enums: ['rectangle', 'roundrectangle', 'cutrectangle', 'bottomroundrectangle', 'barrel', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'concavehexagon', 'heptagon', 'octagon', 'tag', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] },
compoundIncludeLabels: { enums: ['include', 'exclude'] },
arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-cross', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] },
arrowFill: { enums: ['filled', 'hollow'] },
display: { enums: ['element', 'none'] },
visibility: { enums: ['hidden', 'visible'] },
zCompoundDepth: { enums: ['bottom', 'orphan', 'auto', 'top'] },
zIndexCompare: { enums: ['auto', 'manual'] },
valign: { enums: ['top', 'center', 'bottom'] },
halign: { enums: ['left', 'center', 'right'] },
text: { string: true },
data: { mapping: true, regex: data('data') },
layoutData: { mapping: true, regex: data('layoutData') },
scratch: { mapping: true, regex: data('scratch') },
mapData: { mapping: true, regex: mapData('mapData') },
mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') },
mapScratch: { mapping: true, regex: mapData('mapScratch') },
fn: { mapping: true, fn: true },
url: { regexes: urlRegexes, singleRegexMatchValue: true },
urls: { regexes: urlRegexes, singleRegexMatchValue: true, multiple: true },
propList: { propList: true },
angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' },
textRotation: { number: true, units: 'deg|rad', implicitUnits: 'rad', enums: ['none', 'autorotate'] },
polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true },
edgeDistances: { enums: ['intersection', 'node-position'] },
edgeEndpoint: {
number: true, multiple: true, units: '%|px|em|deg|rad', implicitUnits: 'px',
enums: ['inside-to-node', 'outside-to-node', 'outside-to-line'], singleEnum: true,
validate: function validate(valArr, unitsArr) {
switch (valArr.length) {
case 2:
// can be % or px only
return unitsArr[0] !== 'deg' && unitsArr[0] !== 'rad' && unitsArr[1] !== 'deg' && unitsArr[1] !== 'rad';
case 1:
// can be enum, deg, or rad only
return is.string(valArr[0]) || unitsArr[0] === 'deg' || unitsArr[0] === 'rad';
default:
return false;
}
}
},
easing: {
regexes: ['^(spring)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$', '^(cubic-bezier)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$'],
enums: ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine', 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad', 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic', 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart', 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint', 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo', 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ']
}
};
var zOrderDiff = {
zeroNonZero: function zeroNonZero(val1, val2) {
if (val1 === 0 && val2 !== 0) {
return true;
} else if (val1 !== 0 && val2 === 0) {
return true;
} else {
return false;
}
},
anyDiff: function anyDiff(val1, val2) {
return val1 !== val2;
}
};
var zd = zOrderDiff;
// define visual style properties
var t = styfn.types;
var props = styfn.properties = [
// main label
{ name: 'label', type: t.text }, { name: 'text-rotation', type: t.textRotation }, { name: 'text-margin-x', type: t.bidirectionalSize }, { name: 'text-margin-y', type: t.bidirectionalSize },
// source label
{ name: 'source-label', type: t.text }, { name: 'source-text-rotation', type: t.textRotation }, { name: 'source-text-margin-x', type: t.bidirectionalSize }, { name: 'source-text-margin-y', type: t.bidirectionalSize }, { name: 'source-text-offset', type: t.size },
// target label
{ name: 'target-label', type: t.text }, { name: 'target-text-rotation', type: t.textRotation }, { name: 'target-text-margin-x', type: t.bidirectionalSize }, { name: 'target-text-margin-y', type: t.bidirectionalSize }, { name: 'target-text-offset', type: t.size },
// common label style
{ name: 'text-valign', type: t.valign }, { name: 'text-halign', type: t.halign }, { name: 'color', type: t.color }, { name: 'text-outline-color', type: t.color }, { name: 'text-outline-width', type: t.size }, { name: 'text-outline-opacity', type: t.zeroOneNumber }, { name: 'text-opacity', type: t.zeroOneNumber }, { name: 'text-background-color', type: t.color }, { name: 'text-background-opacity', type: t.zeroOneNumber }, { name: 'text-background-padding', type: t.size }, { name: 'text-border-opacity', type: t.zeroOneNumber }, { name: 'text-border-color', type: t.color }, { name: 'text-border-width', type: t.size }, { name: 'text-border-style', type: t.borderStyle }, { name: 'text-background-shape', type: t.textBackgroundShape },
// { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas
{ name: 'text-transform', type: t.textTransform }, { name: 'text-wrap', type: t.textWrap }, { name: 'text-max-width', type: t.size }, { name: 'text-events', type: t.bool }, { name: 'font-family', type: t.fontFamily }, { name: 'font-style', type: t.fontStyle },
// { name: 'font-letiant', type: t.fontletiant }, // not useful
{ name: 'font-weight', type: t.fontWeight }, { name: 'font-size', type: t.size }, { name: 'min-zoomed-font-size', type: t.size },
// behaviour
{ name: 'events', type: t.bool },
// visibility
{ name: 'display', type: t.display, triggersZOrder: zd.anyDiff }, { name: 'visibility', type: t.visibility, triggersZOrder: zd.anyDiff }, { name: 'opacity', type: t.zeroOneNumber, triggersZOrder: zd.zeroNonZero }, { name: 'z-compound-depth', type: t.zCompoundDepth, triggersZOrder: zd.anyDiff }, { name: 'z-index-compare', type: t.zIndexCompare, triggersZOrder: zd.anyDiff }, { name: 'z-index', type: t.nonNegativeInt, triggersZOrder: zd.anyDiff },
// overlays
{ name: 'overlay-padding', type: t.size }, { name: 'overlay-color', type: t.color }, { name: 'overlay-opacity', type: t.zeroOneNumber },
// transition anis
{ name: 'transition-property', type: t.propList }, { name: 'transition-duration', type: t.time }, { name: 'transition-delay', type: t.time }, { name: 'transition-timing-function', type: t.easing },
// node body
{ name: 'height', type: t.nodeSize }, { name: 'width', type: t.nodeSize }, { name: 'shape', type: t.nodeShape }, { name: 'shape-polygon-points', type: t.polygonPointList }, { name: 'background-color', type: t.color }, { name: 'background-opacity', type: t.zeroOneNumber }, { name: 'background-blacken', type: t.nOneOneNumber }, { name: 'padding', type: t.sizeMaybePercent }, { name: 'padding-relative-to', type: t.paddingRelativeTo },
// node border
{ name: 'border-color', type: t.color }, { name: 'border-opacity', type: t.zeroOneNumber }, { name: 'border-width', type: t.size }, { name: 'border-style', type: t.borderStyle },
// node background images
{ name: 'background-image', type: t.urls }, { name: 'background-image-crossorigin', type: t.bgCrossOrigin }, { name: 'background-image-opacity', type: t.zeroOneNumbers }, { name: 'background-position-x', type: t.bgPos }, { name: 'background-position-y', type: t.bgPos }, { name: 'background-width-relative-to', type: t.bgRelativeTo }, { name: 'background-height-relative-to', type: t.bgRelativeTo }, { name: 'background-repeat', type: t.bgRepeat }, { name: 'background-fit', type: t.bgFit }, { name: 'background-clip', type: t.bgClip }, { name: 'background-width', type: t.bgWH }, { name: 'background-height', type: t.bgWH },
// compound props
{ name: 'position', type: t.position }, { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels }, { name: 'min-width', type: t.size }, { name: 'min-width-bias-left', type: t.sizeMaybePercent }, { name: 'min-width-bias-right', type: t.sizeMaybePercent }, { name: 'min-height', type: t.size }, { name: 'min-height-bias-top', type: t.sizeMaybePercent }, { name: 'min-height-bias-bottom', type: t.sizeMaybePercent },
// edge line
{ name: 'line-style', type: t.lineStyle }, { name: 'line-color', type: t.color }, { name: 'curve-style', type: t.curveStyle }, { name: 'haystack-radius', type: t.zeroOneNumber }, { name: 'source-endpoint', type: t.edgeEndpoint }, { name: 'target-endpoint', type: t.edgeEndpoint }, { name: 'control-point-step-size', type: t.size }, { name: 'control-point-distances', type: t.bidirectionalSizes }, { name: 'control-point-weights', type: t.numbers }, { name: 'segment-distances', type: t.bidirectionalSizes }, { name: 'segment-weights', type: t.numbers }, { name: 'edge-distances', type: t.edgeDistances }, { name: 'arrow-scale', type: t.positiveNumber }, { name: 'loop-direction', type: t.angle }, { name: 'loop-sweep', type: t.angle }, { name: 'source-distance-from-node', type: t.size }, { name: 'target-distance-from-node', type: t.size },
// ghost properties
{ name: 'ghost', type: t.bool }, { name: 'ghost-offset-x', type: t.bidirectionalSize }, { name: 'ghost-offset-y', type: t.bidirectionalSize }, { name: 'ghost-opacity', type: t.zeroOneNumber },
// these are just for the core
{ name: 'selection-box-color', type: t.color }, { name: 'selection-box-opacity', type: t.zeroOneNumber }, { name: 'selection-box-border-color', type: t.color }, { name: 'selection-box-border-width', type: t.size }, { name: 'active-bg-color', type: t.color }, { name: 'active-bg-opacity', type: t.zeroOneNumber }, { name: 'active-bg-size', type: t.size }, { name: 'outside-texture-bg-color', type: t.color }, { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }];
// define aliases
var aliases = styfn.aliases = [{ name: 'content', pointsTo: 'label' }, { name: 'control-point-distance', pointsTo: 'control-point-distances' }, { name: 'control-point-weight', pointsTo: 'control-point-weights' }, { name: 'edge-text-rotation', pointsTo: 'text-rotation' }, { name: 'padding-left', pointsTo: 'padding' }, { name: 'padding-right', pointsTo: 'padding' }, { name: 'padding-top', pointsTo: 'padding' }, { name: 'padding-bottom', pointsTo: 'padding' }];
// pie backgrounds for nodes
styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)
props.push({ name: 'pie-size', type: t.sizeMaybePercent });
for (var i = 1; i <= styfn.pieBackgroundN; i++) {
props.push({ name: 'pie-' + i + '-background-color', type: t.color });
props.push({ name: 'pie-' + i + '-background-size', type: t.percent });
props.push({ name: 'pie-' + i + '-background-opacity', type: t.zeroOneNumber });
}
// edge arrows
var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];
[{ name: 'arrow-shape', type: t.arrowShape }, { name: 'arrow-color', type: t.color }, { name: 'arrow-fill', type: t.arrowFill }].forEach(function (prop) {
arrowPrefixes.forEach(function (prefix) {
var name = prefix + '-' + prop.name;
var type = prop.type;
props.push({ name: name, type: type });
});
}, {});
// list of property names
styfn.propertyNames = props.map(function (p) {
return p.name;
});
// allow access of properties by name ( e.g. style.properties.height )
for (var _i = 0; _i < props.length; _i++) {
var prop = props[_i];
props[prop.name] = prop; // allow lookup by name
}
// map aliases
for (var _i2 = 0; _i2 < aliases.length; _i2++) {
var alias = aliases[_i2];
var pointsToProp = props[alias.pointsTo];
var aliasProp = {
name: alias.name,
alias: true,
pointsTo: pointsToProp
};
// add alias prop for parsing
props.push(aliasProp);
props[alias.name] = aliasProp; // allow lookup by name
}
})();
styfn.getDefaultProperty = function (name) {
return this.getDefaultProperties()[name];
};
styfn.getDefaultProperties = util.memoize(function () {
var rawProps = util.extend({
// common node/edge props
'events': 'yes',
'text-events': 'no',
'text-valign': 'top',
'text-halign': 'center',
'color': '#000',
'text-outline-color': '#000',
'text-outline-width': 0,
'text-outline-opacity': 1,
'text-opacity': 1,
'text-decoration': 'none',
'text-transform': 'none',
'text-wrap': 'none',
'text-max-width': 9999,
'text-background-color': '#000',
'text-background-opacity': 0,
'text-background-shape': 'rectangle',
'text-background-padding': 0,
'text-border-opacity': 0,
'text-border-width': 0,
'text-border-style': 'solid',
'text-border-color': '#000',
'font-family': 'Helvetica Neue, Helvetica, sans-serif',
'font-style': 'normal',
// 'font-letiant': fontletiant,
'font-weight': 'normal',
'font-size': 16,
'min-zoomed-font-size': 0,
'text-rotation': 'none',
'source-text-rotation': 'none',
'target-text-rotation': 'none',
'visibility': 'visible',
'display': 'element',
'opacity': 1,
'z-compound-depth': 'auto',
'z-index-compare': 'auto',
'z-index': 0,
'label': '',
'text-margin-x': 0,
'text-margin-y': 0,
'source-label': '',
'source-text-offset': 0,
'source-text-margin-x': 0,
'source-text-margin-y': 0,
'target-label': '',
'target-text-offset': 0,
'target-text-margin-x': 0,
'target-text-margin-y': 0,
'overlay-opacity': 0,
'overlay-color': '#000',
'overlay-padding': 10,
'transition-property': 'none',
'transition-duration': 0,
'transition-delay': 0,
'transition-timing-function': 'linear',
// node props
'background-blacken': 0,
'background-color': '#999',
'background-opacity': 1,
'background-image': 'none',
'background-image-crossorigin': 'anonymous',
'background-image-opacity': 1,
'background-position-x': '50%',
'background-position-y': '50%',
'background-width-relative-to': 'include-padding',
'background-height-relative-to': 'include-padding',
'background-repeat': 'no-repeat',
'background-fit': 'none',
'background-clip': 'node',
'background-width': 'auto',
'background-height': 'auto',
'border-color': '#000',
'border-opacity': 1,
'border-width': 0,
'border-style': 'solid',
'height': 30,
'width': 30,
'shape': 'ellipse',
'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1',
// ghost props
'ghost': 'no',
'ghost-offset-y': 0,
'ghost-offset-x': 0,
'ghost-opacity': 0,
// compound props
'padding': 0,
'padding-relative-to': 'width',
'position': 'origin',
'compound-sizing-wrt-labels': 'include',
'min-width': 0,
'min-width-bias-left': 0,
'min-width-bias-right': 0,
'min-height': 0,
'min-height-bias-top': 0,
'min-height-bias-bottom': 0
}, {
// node pie bg
'pie-size': '100%'
}, [{ name: 'pie-{{i}}-background-color', value: 'black' }, { name: 'pie-{{i}}-background-size', value: '0%' }, { name: 'pie-{{i}}-background-opacity', value: 1 }].reduce(function (css, prop) {
for (var i = 1; i <= styfn.pieBackgroundN; i++) {
var name = prop.name.replace('{{i}}', i);
var val = prop.value;
css[name] = val;
}
return css;
}, {}), {
// edge props
'line-style': 'solid',
'line-color': '#999',
'control-point-step-size': 40,
'control-point-weights': 0.5,
'segment-weights': 0.5,
'segment-distances': 20,
'edge-distances': 'intersection',
'curve-style': 'bezier',
'haystack-radius': 0,
'arrow-scale': 1,
'loop-direction': '-45deg',
'loop-sweep': '-90deg',
'source-distance-from-node': 0,
'target-distance-from-node': 0,
'source-endpoint': 'outside-to-node',
'target-endpoint': 'outside-to-node'
}, [{ name: 'arrow-shape', value: 'none' }, { name: 'arrow-color', value: '#999' }, { name: 'arrow-fill', value: 'filled' }].reduce(function (css, prop) {
styfn.arrowPrefixes.forEach(function (prefix) {
var name = prefix + '-' + prop.name;
var val = prop.value;
css[name] = val;
});
return css;
}, {}));
var parsedProps = {};
for (var i = 0; i < this.properties.length; i++) {
var prop = this.properties[i];
if (prop.pointsTo) {
continue;
}
var name = prop.name;
var val = rawProps[name];
var parsedProp = this.parse(name, val);
parsedProps[name] = parsedProp;
}
return parsedProps;
});
styfn.addDefaultStylesheet = function () {
this.selector('$node > node') // compound (parent) node properties
.css({
'shape': 'rectangle',
'padding': 10,
'background-color': '#eee',
'border-color': '#ccc',
'border-width': 1
}).selector('edge') // just edge properties
.css({
'width': 3,
'curve-style': 'haystack'
}).selector(':parent <-> node').css({
'curve-style': 'bezier',
'source-endpoint': 'outside-to-line',
'target-endpoint': 'outside-to-line'
}).selector(':selected').css({
'background-color': '#0169D9',
'line-color': '#0169D9',
'source-arrow-color': '#0169D9',
'target-arrow-color': '#0169D9',
'mid-source-arrow-color': '#0169D9',
'mid-target-arrow-color': '#0169D9'
}).selector('node:parent:selected').css({
'background-color': '#CCE1F9',
'border-color': '#aec8e5'
}).selector(':active').css({
'overlay-color': 'black',
'overlay-padding': 10,
'overlay-opacity': 0.25
}).selector('core') // just core properties
.css({
'selection-box-color': '#ddd',
'selection-box-opacity': 0.65,
'selection-box-border-color': '#aaa',
'selection-box-border-width': 1,
'active-bg-color': 'black',
'active-bg-opacity': 0.15,
'active-bg-size': 30,
'outside-texture-bg-color': '#000',
'outside-texture-bg-opacity': 0.125
});
this.defaultLength = this.length;
};
module.exports = styfn;
/***/ }),
/* 93 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var math = __webpack_require__(2);
var styfn = {};
// a caching layer for property parsing
styfn.parse = function (name, value, propIsBypass, propIsFlat) {
var self = this;
// function values can't be cached in all cases, and there isn't much benefit of caching them anyway
if (is.fn(value)) {
return self.parseImplWarn(name, value, propIsBypass, propIsFlat);
}
var flatKey = propIsFlat === 'mapping' || propIsFlat === true || propIsFlat === false || propIsFlat == null ? 'dontcare' : propIsFlat;
var argHash = [name, value, propIsBypass, flatKey].join('$');
var propCache = self.propCache = self.propCache || {};
var ret = void 0;
if (!(ret = propCache[argHash])) {
ret = propCache[argHash] = self.parseImplWarn(name, value, propIsBypass, propIsFlat);
}
// - bypasses can't be shared b/c the value can be changed by animations or otherwise overridden
// - mappings can't be shared b/c mappings are per-element
if (propIsBypass || propIsFlat === 'mapping') {
// need a copy since props are mutated later in their lifecycles
ret = util.copy(ret);
if (ret) {
ret.value = util.copy(ret.value); // because it could be an array, e.g. colour
}
}
return ret;
};
styfn.parseImplWarn = function (name, value, propIsBypass, propIsFlat) {
var prop = this.parseImpl(name, value, propIsBypass, propIsFlat);
if (!prop && value != null) {
util.error('The style property `%s: %s` is invalid', name, value);
}
return prop;
};
// parse a property; return null on invalid; return parsed property otherwise
// fields :
// - name : the name of the property
// - value : the parsed, native-typed value of the property
// - strValue : a string value that represents the property value in valid css
// - bypass : true iff the property is a bypass property
styfn.parseImpl = function (name, value, propIsBypass, propIsFlat) {
var self = this;
name = util.camel2dash(name); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')
var property = self.properties[name];
var passedValue = value;
var types = self.types;
if (!property) {
return null;
} // return null on property of unknown name
if (value === undefined) {
return null;
} // can't assign undefined
// the property may be an alias
if (property.alias) {
property = property.pointsTo;
name = property.name;
}
var valueIsString = is.string(value);
if (valueIsString) {
// trim the value to make parsing easier
value = value.trim();
}
var type = property.type;
if (!type) {
return null;
} // no type, no luck
// check if bypass is null or empty string (i.e. indication to delete bypass property)
if (propIsBypass && (value === '' || value === null)) {
return {
name: name,
value: value,
bypass: true,
deleteBypass: true
};
}
// check if value is a function used as a mapper
if (is.fn(value)) {
return {
name: name,
value: value,
strValue: 'fn',
mapped: types.fn,
bypass: propIsBypass
};
}
// check if value is mapped
var data = void 0,
mapData = void 0;
if (!valueIsString || propIsFlat) {
// then don't bother to do the expensive regex checks
} else if (data = new RegExp(types.data.regex).exec(value)) {
if (propIsBypass) {
return false;
} // mappers not allowed in bypass
var mapped = types.data;
return {
name: name,
value: data,
strValue: '' + value,
mapped: mapped,
field: data[1],
bypass: propIsBypass
};
} else if (mapData = new RegExp(types.mapData.regex).exec(value)) {
if (propIsBypass) {
return false;
} // mappers not allowed in bypass
if (type.multiple) {
return false;
} // impossible to map to num
var _mapped = types.mapData;
// we can map only if the type is a colour or a number
if (!(type.color || type.number)) {
return false;
}
var valueMin = this.parse(name, mapData[4]); // parse to validate
if (!valueMin || valueMin.mapped) {
return false;
} // can't be invalid or mapped
var valueMax = this.parse(name, mapData[5]); // parse to validate
if (!valueMax || valueMax.mapped) {
return false;
} // can't be invalid or mapped
// check if valueMin and valueMax are the same
if (valueMin.value === valueMax.value) {
return false; // can't make much of a mapper without a range
} else if (type.color) {
var c1 = valueMin.value;
var c2 = valueMax.value;
var same = c1[0] === c2[0] // red
&& c1[1] === c2[1] // green
&& c1[2] === c2[2] // blue
&& ( // optional alpha
c1[3] === c2[3] // same alpha outright
|| (c1[3] == null || c1[3] === 1) && ( // full opacity for colour 1?
c2[3] == null || c2[3] === 1) // full opacity for colour 2?
);
if (same) {
return false;
} // can't make a mapper without a range
}
return {
name: name,
value: mapData,
strValue: '' + value,
mapped: _mapped,
field: mapData[1],
fieldMin: parseFloat(mapData[2]), // min & max are numeric
fieldMax: parseFloat(mapData[3]),
valueMin: valueMin.value,
valueMax: valueMax.value,
bypass: propIsBypass
};
}
if (type.multiple && propIsFlat !== 'multiple') {
var vals = void 0;
if (valueIsString) {
vals = value.split(/\s+/);
} else if (is.array(value)) {
vals = value;
} else {
vals = [value];
}
if (type.evenMultiple && vals.length % 2 !== 0) {
return null;
}
var valArr = [];
var unitsArr = [];
var pfValArr = [];
var hasEnum = false;
for (var i = 0; i < vals.length; i++) {
var p = self.parse(name, vals[i], propIsBypass, 'multiple');
hasEnum = hasEnum || is.string(p.value);
valArr.push(p.value);
pfValArr.push(p.pfValue != null ? p.pfValue : p.value);
unitsArr.push(p.units);
}
if (type.validate && !type.validate(valArr, unitsArr)) {
return null;
}
if (type.singleEnum && hasEnum) {
if (valArr.length === 1 && is.string(valArr[0])) {
return {
name: name,
value: valArr[0],
strValue: valArr[0],
bypass: propIsBypass
};
} else {
return null;
}
}
return {
name: name,
value: valArr,
pfValue: pfValArr,
strValue: valArr.map(function (val, i) {
return val + (unitsArr[i] || '');
}).join(' '),
bypass: propIsBypass,
units: unitsArr
};
}
// several types also allow enums
var checkEnums = function checkEnums() {
for (var _i = 0; _i < type.enums.length; _i++) {
var en = type.enums[_i];
if (en === value) {
return {
name: name,
value: value,
strValue: '' + value,
bypass: propIsBypass
};
}
}
return null;
};
// check the type and return the appropriate object
if (type.number) {
var units = void 0;
var implicitUnits = 'px'; // not set => px
if (type.units) {
// use specified units if set
units = type.units;
}
if (type.implicitUnits) {
implicitUnits = type.implicitUnits;
}
if (!type.unitless) {
if (valueIsString) {
var unitsRegex = 'px|em' + (type.allowPercent ? '|\\%' : '');
if (units) {
unitsRegex = units;
} // only allow explicit units if so set
var match = value.match('^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$');
if (match) {
value = match[1];
units = match[2] || implicitUnits;
}
} else if (!units || type.implicitUnits) {
units = implicitUnits; // implicitly px if unspecified
}
}
value = parseFloat(value);
// if not a number and enums not allowed, then the value is invalid
if (isNaN(value) && type.enums === undefined) {
return null;
}
// check if this number type also accepts special keywords in place of numbers
// (i.e. `left`, `auto`, etc)
if (isNaN(value) && type.enums !== undefined) {
value = passedValue;
return checkEnums();
}
// check if value must be an integer
if (type.integer && !is.integer(value)) {
return null;
}
// check value is within range
if (type.min !== undefined && (value < type.min || type.strictMin && value === type.min) || type.max !== undefined && (value > type.max || type.strictMax && value === type.max)) {
return null;
}
var ret = {
name: name,
value: value,
strValue: '' + value + (units ? units : ''),
units: units,
bypass: propIsBypass
};
// normalise value in pixels
if (type.unitless || units !== 'px' && units !== 'em') {
ret.pfValue = value;
} else {
ret.pfValue = units === 'px' || !units ? value : this.getEmSizeInPixels() * value;
}
// normalise value in ms
if (units === 'ms' || units === 's') {
ret.pfValue = units === 'ms' ? value : 1000 * value;
}
// normalise value in rad
if (units === 'deg' || units === 'rad') {
ret.pfValue = units === 'rad' ? value : math.deg2rad(value);
}
// normalize value in %
if (units === '%') {
ret.pfValue = value / 100;
}
return ret;
} else if (type.propList) {
var props = [];
var propsStr = '' + value;
if (propsStr === 'none') {
// leave empty
} else {
// go over each prop
var propsSplit = propsStr.split(',');
for (var _i2 = 0; _i2 < propsSplit.length; _i2++) {
var propName = propsSplit[_i2].trim();
if (self.properties[propName]) {
props.push(propName);
}
}
if (props.length === 0) {
return null;
}
}
return {
name: name,
value: props,
strValue: props.length === 0 ? 'none' : props.join(', '),
bypass: propIsBypass
};
} else if (type.color) {
var tuple = util.color2tuple(value);
if (!tuple) {
return null;
}
return {
name: name,
value: tuple,
pfValue: tuple,
strValue: '' + value,
bypass: propIsBypass
};
} else if (type.regex || type.regexes) {
// first check enums
if (type.enums) {
var enumProp = checkEnums();
if (enumProp) {
return enumProp;
}
}
var regexes = type.regexes ? type.regexes : [type.regex];
for (var _i3 = 0; _i3 < regexes.length; _i3++) {
var regex = new RegExp(regexes[_i3]); // make a regex from the type string
var m = regex.exec(value);
if (m) {
// regex matches
return {
name: name,
value: type.singleRegexMatchValue ? m[1] : m,
strValue: '' + value,
bypass: propIsBypass
};
}
}
return null; // didn't match any
} else if (type.string) {
// just return
return {
name: name,
value: '' + value,
strValue: '' + value,
bypass: propIsBypass
};
} else if (type.enums) {
// check enums last because it's a combo type in others
return checkEnums();
} else {
return null; // not a type we can handle
}
};
module.exports = styfn;
/***/ }),
/* 94 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var window = __webpack_require__(3);
var math = __webpack_require__(2);
var corefn = {
autolock: function autolock(bool) {
if (bool !== undefined) {
this._private.autolock = bool ? true : false;
} else {
return this._private.autolock;
}
return this; // chaining
},
autoungrabify: function autoungrabify(bool) {
if (bool !== undefined) {
this._private.autoungrabify = bool ? true : false;
} else {
return this._private.autoungrabify;
}
return this; // chaining
},
autounselectify: function autounselectify(bool) {
if (bool !== undefined) {
this._private.autounselectify = bool ? true : false;
} else {
return this._private.autounselectify;
}
return this; // chaining
},
panningEnabled: function panningEnabled(bool) {
if (bool !== undefined) {
this._private.panningEnabled = bool ? true : false;
} else {
return this._private.panningEnabled;
}
return this; // chaining
},
userPanningEnabled: function userPanningEnabled(bool) {
if (bool !== undefined) {
this._private.userPanningEnabled = bool ? true : false;
} else {
return this._private.userPanningEnabled;
}
return this; // chaining
},
zoomingEnabled: function zoomingEnabled(bool) {
if (bool !== undefined) {
this._private.zoomingEnabled = bool ? true : false;
} else {
return this._private.zoomingEnabled;
}
return this; // chaining
},
userZoomingEnabled: function userZoomingEnabled(bool) {
if (bool !== undefined) {
this._private.userZoomingEnabled = bool ? true : false;
} else {
return this._private.userZoomingEnabled;
}
return this; // chaining
},
boxSelectionEnabled: function boxSelectionEnabled(bool) {
if (bool !== undefined) {
this._private.boxSelectionEnabled = bool ? true : false;
} else {
return this._private.boxSelectionEnabled;
}
return this; // chaining
},
pan: function pan() {
var args = arguments;
var pan = this._private.pan;
var dim = void 0,
val = void 0,
dims = void 0,
x = void 0,
y = void 0;
switch (args.length) {
case 0:
// .pan()
return pan;
case 1:
if (is.string(args[0])) {
// .pan('x')
dim = args[0];
return pan[dim];
} else if (is.plainObject(args[0])) {
// .pan({ x: 0, y: 100 })
if (!this._private.panningEnabled) {
return this;
}
dims = args[0];
x = dims.x;
y = dims.y;
if (is.number(x)) {
pan.x = x;
}
if (is.number(y)) {
pan.y = y;
}
this.emit('pan viewport');
}
break;
case 2:
// .pan('x', 100)
if (!this._private.panningEnabled) {
return this;
}
dim = args[0];
val = args[1];
if ((dim === 'x' || dim === 'y') && is.number(val)) {
pan[dim] = val;
}
this.emit('pan viewport');
break;
default:
break; // invalid
}
this.notify({ // notify the renderer that the viewport changed
type: 'viewport'
});
return this; // chaining
},
panBy: function panBy(arg0, arg1) {
var args = arguments;
var pan = this._private.pan;
var dim = void 0,
val = void 0,
dims = void 0,
x = void 0,
y = void 0;
if (!this._private.panningEnabled) {
return this;
}
switch (args.length) {
case 1:
if (is.plainObject(arg0)) {
// .panBy({ x: 0, y: 100 })
dims = args[0];
x = dims.x;
y = dims.y;
if (is.number(x)) {
pan.x += x;
}
if (is.number(y)) {
pan.y += y;
}
this.emit('pan viewport');
}
break;
case 2:
// .panBy('x', 100)
dim = arg0;
val = arg1;
if ((dim === 'x' || dim === 'y') && is.number(val)) {
pan[dim] += val;
}
this.emit('pan viewport');
break;
default:
break; // invalid
}
this.notify({ // notify the renderer that the viewport changed
type: 'viewport'
});
return this; // chaining
},
fit: function fit(elements, padding) {
var viewportState = this.getFitViewport(elements, padding);
if (viewportState) {
var _p = this._private;
_p.zoom = viewportState.zoom;
_p.pan = viewportState.pan;
this.emit('pan zoom viewport');
this.notify({ // notify the renderer that the viewport changed
type: 'viewport'
});
}
return this; // chaining
},
getFitViewport: function getFitViewport(elements, padding) {
if (is.number(elements) && padding === undefined) {
// elements is optional
padding = elements;
elements = undefined;
}
if (!this._private.panningEnabled || !this._private.zoomingEnabled) {
return;
}
var bb = void 0;
if (is.string(elements)) {
var sel = elements;
elements = this.$(sel);
} else if (is.boundingBox(elements)) {
// assume bb
var bbe = elements;
bb = {
x1: bbe.x1,
y1: bbe.y1,
x2: bbe.x2,
y2: bbe.y2
};
bb.w = bb.x2 - bb.x1;
bb.h = bb.y2 - bb.y1;
} else if (!is.elementOrCollection(elements)) {
elements = this.mutableElements();
}
if (is.elementOrCollection(elements) && elements.empty()) {
return;
} // can't fit to nothing
bb = bb || elements.boundingBox();
var w = this.width();
var h = this.height();
var zoom = void 0;
padding = is.number(padding) ? padding : 0;
if (!isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) && bb.w > 0 && bb.h > 0) {
zoom = Math.min((w - 2 * padding) / bb.w, (h - 2 * padding) / bb.h);
// crop zoom
zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;
zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;
var pan = { // now pan to middle
x: (w - zoom * (bb.x1 + bb.x2)) / 2,
y: (h - zoom * (bb.y1 + bb.y2)) / 2
};
return {
zoom: zoom,
pan: pan
};
}
return;
},
minZoom: function minZoom(zoom) {
if (zoom === undefined) {
return this._private.minZoom;
} else if (is.number(zoom)) {
this._private.minZoom = zoom;
}
return this;
},
maxZoom: function maxZoom(zoom) {
if (zoom === undefined) {
return this._private.maxZoom;
} else if (is.number(zoom)) {
this._private.maxZoom = zoom;
}
return this;
},
getZoomedViewport: function getZoomedViewport(params) {
var _p = this._private;
var currentPan = _p.pan;
var currentZoom = _p.zoom;
var pos = void 0; // in rendered px
var zoom = void 0;
var bail = false;
if (!_p.zoomingEnabled) {
// zooming disabled
bail = true;
}
if (is.number(params)) {
// then set the zoom
zoom = params;
} else if (is.plainObject(params)) {
// then zoom about a point
zoom = params.level;
if (params.position != null) {
pos = math.modelToRenderedPosition(params.position, currentZoom, currentPan);
} else if (params.renderedPosition != null) {
pos = params.renderedPosition;
}
if (pos != null && !_p.panningEnabled) {
// panning disabled
bail = true;
}
}
// crop zoom
zoom = zoom > _p.maxZoom ? _p.maxZoom : zoom;
zoom = zoom < _p.minZoom ? _p.minZoom : zoom;
// can't zoom with invalid params
if (bail || !is.number(zoom) || zoom === currentZoom || pos != null && (!is.number(pos.x) || !is.number(pos.y))) {
return null;
}
if (pos != null) {
// set zoom about position
var pan1 = currentPan;
var zoom1 = currentZoom;
var zoom2 = zoom;
var pan2 = {
x: -zoom2 / zoom1 * (pos.x - pan1.x) + pos.x,
y: -zoom2 / zoom1 * (pos.y - pan1.y) + pos.y
};
return {
zoomed: true,
panned: true,
zoom: zoom2,
pan: pan2
};
} else {
// just set the zoom
return {
zoomed: true,
panned: false,
zoom: zoom,
pan: currentPan
};
}
},
zoom: function zoom(params) {
if (params === undefined) {
// get
return this._private.zoom;
} else {
// set
var vp = this.getZoomedViewport(params);
var _p = this._private;
if (vp == null || !vp.zoomed) {
return this;
}
_p.zoom = vp.zoom;
if (vp.panned) {
_p.pan.x = vp.pan.x;
_p.pan.y = vp.pan.y;
}
this.emit('zoom' + (vp.panned ? ' pan' : '') + ' viewport');
this.notify({ // notify the renderer that the viewport changed
type: 'viewport'
});
return this; // chaining
}
},
viewport: function viewport(opts) {
var _p = this._private;
var zoomDefd = true;
var panDefd = true;
var events = []; // to trigger
var zoomFailed = false;
var panFailed = false;
if (!opts) {
return this;
}
if (!is.number(opts.zoom)) {
zoomDefd = false;
}
if (!is.plainObject(opts.pan)) {
panDefd = false;
}
if (!zoomDefd && !panDefd) {
return this;
}
if (zoomDefd) {
var z = opts.zoom;
if (z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled) {
zoomFailed = true;
} else {
_p.zoom = z;
events.push('zoom');
}
}
if (panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled) {
var p = opts.pan;
if (is.number(p.x)) {
_p.pan.x = p.x;
panFailed = false;
}
if (is.number(p.y)) {
_p.pan.y = p.y;
panFailed = false;
}
if (!panFailed) {
events.push('pan');
}
}
if (events.length > 0) {
events.push('viewport');
this.emit(events.join(' '));
this.notify({
type: 'viewport'
});
}
return this; // chaining
},
center: function center(elements) {
var pan = this.getCenterPan(elements);
if (pan) {
this._private.pan = pan;
this.emit('pan viewport');
this.notify({ // notify the renderer that the viewport changed
type: 'viewport'
});
}
return this; // chaining
},
getCenterPan: function getCenterPan(elements, zoom) {
if (!this._private.panningEnabled) {
return;
}
if (is.string(elements)) {
var selector = elements;
elements = this.mutableElements().filter(selector);
} else if (!is.elementOrCollection(elements)) {
elements = this.mutableElements();
}
if (elements.length === 0) {
return;
} // can't centre pan to nothing
var bb = elements.boundingBox();
var w = this.width();
var h = this.height();
zoom = zoom === undefined ? this._private.zoom : zoom;
var pan = { // middle
x: (w - zoom * (bb.x1 + bb.x2)) / 2,
y: (h - zoom * (bb.y1 + bb.y2)) / 2
};
return pan;
},
reset: function reset() {
if (!this._private.panningEnabled || !this._private.zoomingEnabled) {
return this;
}
this.viewport({
pan: { x: 0, y: 0 },
zoom: 1
});
return this; // chaining
},
invalidateSize: function invalidateSize() {
this._private.sizeCache = null;
},
size: function size() {
var _p = this._private;
var container = _p.container;
return _p.sizeCache = _p.sizeCache || (container ? function () {
var style = window.getComputedStyle(container);
var val = function val(name) {
return parseFloat(style.getPropertyValue(name));
};
return {
width: container.clientWidth - val('padding-left') - val('padding-right'),
height: container.clientHeight - val('padding-top') - val('padding-bottom')
};
}() : { // fallback if no container (not 0 b/c can be used for dividing etc)
width: 1,
height: 1
});
},
width: function width() {
return this.size().width;
},
height: function height() {
return this.size().height;
},
extent: function extent() {
var pan = this._private.pan;
var zoom = this._private.zoom;
var rb = this.renderedExtent();
var b = {
x1: (rb.x1 - pan.x) / zoom,
x2: (rb.x2 - pan.x) / zoom,
y1: (rb.y1 - pan.y) / zoom,
y2: (rb.y2 - pan.y) / zoom
};
b.w = b.x2 - b.x1;
b.h = b.y2 - b.y1;
return b;
},
renderedExtent: function renderedExtent() {
var width = this.width();
var height = this.height();
return {
x1: 0,
y1: 0,
x2: width,
y2: height,
w: width,
h: height
};
}
};
// aliases
corefn.centre = corefn.center;
// backwards compatibility
corefn.autolockNodes = corefn.autolock;
corefn.autoungrabifyNodes = corefn.autoungrabify;
module.exports = corefn;
/***/ }),
/* 95 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var define = __webpack_require__(4);
var Collection = __webpack_require__(7);
var Core = __webpack_require__(12);
var incExts = __webpack_require__(96);
var is = __webpack_require__(0);
var Emitter = __webpack_require__(11);
// registered extensions to cytoscape, indexed by name
var extensions = {};
// registered modules for extensions, indexed by name
var modules = {};
function setExtension(type, name, registrant) {
var ext = registrant;
var overrideErr = function overrideErr(field) {
util.error('Can not register `' + name + '` for `' + type + '` since `' + field + '` already exists in the prototype and can not be overridden');
};
if (type === 'core') {
if (Core.prototype[name]) {
return overrideErr(name);
} else {
Core.prototype[name] = registrant;
}
} else if (type === 'collection') {
if (Collection.prototype[name]) {
return overrideErr(name);
} else {
Collection.prototype[name] = registrant;
}
} else if (type === 'layout') {
// fill in missing layout functions in the prototype
var Layout = function Layout(options) {
this.options = options;
registrant.call(this, options);
// make sure layout has _private for use w/ std apis like .on()
if (!is.plainObject(this._private)) {
this._private = {};
}
this._private.cy = options.cy;
this._private.listeners = [];
this.createEmitter();
};
var layoutProto = Layout.prototype = Object.create(registrant.prototype);
var optLayoutFns = [];
for (var i = 0; i < optLayoutFns.length; i++) {
var fnName = optLayoutFns[i];
layoutProto[fnName] = layoutProto[fnName] || function () {
return this;
};
}
// either .start() or .run() is defined, so autogen the other
if (layoutProto.start && !layoutProto.run) {
layoutProto.run = function () {
this.start();return this;
};
} else if (!layoutProto.start && layoutProto.run) {
layoutProto.start = function () {
this.run();return this;
};
}
var regStop = registrant.prototype.stop;
layoutProto.stop = function () {
var opts = this.options;
if (opts && opts.animate) {
var anis = this.animations;
if (anis) {
for (var _i = 0; _i < anis.length; _i++) {
anis[_i].stop();
}
}
}
if (regStop) {
regStop.call(this);
} else {
this.emit('layoutstop');
}
return this;
};
if (!layoutProto.destroy) {
layoutProto.destroy = function () {
return this;
};
}
layoutProto.cy = function () {
return this._private.cy;
};
var getCy = function getCy(layout) {
return layout._private.cy;
};
util.assign(layoutProto, {
createEmitter: function createEmitter() {
this._private.emitter = new Emitter({
eventFields: function eventFields(layout) {
return {
layout: layout,
cy: getCy(layout),
target: layout
};
},
bubble: function bubble() {
return true;
},
parent: function parent(layout) {
return getCy(layout);
},
context: this
});
return this;
},
emitter: function emitter() {
return this._private.emitter;
},
on: function on(evt, cb) {
this.emitter().on(evt, cb);return this;
},
one: function one(evt, cb) {
this.emitter().one(evt, cb);return this;
},
once: function once(evt, cb) {
this.emitter().one(evt, cb);return this;
},
removeListener: function removeListener(evt, cb) {
this.emitter().removeListener(evt, cb);return this;
},
emit: function emit(evt, params) {
this.emitter().emit(evt, params);return this;
}
});
define.eventAliasesOn(layoutProto);
ext = Layout; // replace with our wrapped layout
} else if (type === 'renderer' && name !== 'null' && name !== 'base') {
// user registered renderers inherit from base
var BaseRenderer = getExtension('renderer', 'base');
var bProto = BaseRenderer.prototype;
var RegistrantRenderer = registrant;
var rProto = registrant.prototype;
var Renderer = function Renderer() {
BaseRenderer.apply(this, arguments);
RegistrantRenderer.apply(this, arguments);
};
var proto = Renderer.prototype;
for (var pName in bProto) {
var pVal = bProto[pName];
var existsInR = rProto[pName] != null;
if (existsInR) {
return overrideErr(pName);
}
proto[pName] = pVal; // take impl from base
}
for (var _pName in rProto) {
proto[_pName] = rProto[_pName]; // take impl from registrant
}
bProto.clientFunctions.forEach(function (name) {
proto[name] = proto[name] || function () {
util.error('Renderer does not implement `renderer.' + name + '()` on its prototype');
};
});
ext = Renderer;
}
return util.setMap({
map: extensions,
keys: [type, name],
value: ext
});
}
function getExtension(type, name) {
return util.getMap({
map: extensions,
keys: [type, name]
});
}
function setModule(type, name, moduleType, moduleName, registrant) {
return util.setMap({
map: modules,
keys: [type, name, moduleType, moduleName],
value: registrant
});
}
function getModule(type, name, moduleType, moduleName) {
return util.getMap({
map: modules,
keys: [type, name, moduleType, moduleName]
});
}
var extension = function extension() {
// e.g. extension('renderer', 'svg')
if (arguments.length === 2) {
return getExtension.apply(null, arguments);
}
// e.g. extension('renderer', 'svg', { ... })
else if (arguments.length === 3) {
return setExtension.apply(null, arguments);
}
// e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')
else if (arguments.length === 4) {
return getModule.apply(null, arguments);
}
// e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })
else if (arguments.length === 5) {
return setModule.apply(null, arguments);
} else {
util.error('Invalid extension access syntax');
}
};
// allows a core instance to access extensions internally
Core.prototype.extension = extension;
// included extensions
incExts.forEach(function (group) {
group.extensions.forEach(function (ext) {
setExtension(group.type, ext.name, ext.impl);
});
});
module.exports = extension;
/***/ }),
/* 96 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = [{
type: 'layout',
extensions: __webpack_require__(97)
}, {
type: 'renderer',
extensions: __webpack_require__(106)
}];
/***/ }),
/* 97 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = [{ name: 'breadthfirst', impl: __webpack_require__(98) }, { name: 'circle', impl: __webpack_require__(99) }, { name: 'concentric', impl: __webpack_require__(100) }, { name: 'cose', impl: __webpack_require__(101) }, { name: 'grid', impl: __webpack_require__(102) }, { name: 'null', impl: __webpack_require__(103) }, { name: 'preset', impl: __webpack_require__(104) }, { name: 'random', impl: __webpack_require__(105) }];
/***/ }),
/* 98 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var defaults = {
fit: true, // whether to fit the viewport to the graph
directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)
padding: 30, // padding on fit
circle: false, // put depths in concentric circles if true, put depths top down if false
spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
roots: undefined, // the roots of the trees
maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking)
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled,
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function BreadthFirstLayout(options) {
this.options = util.extend({}, defaults, options);
}
BreadthFirstLayout.prototype.run = function () {
var params = this.options;
var options = params;
var cy = params.cy;
var eles = options.eles;
var nodes = eles.nodes().not(':parent');
var graph = eles;
var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
});
var roots = void 0;
if (is.elementOrCollection(options.roots)) {
roots = options.roots;
} else if (is.array(options.roots)) {
var rootsArray = [];
for (var i = 0; i < options.roots.length; i++) {
var id = options.roots[i];
var ele = cy.getElementById(id);
rootsArray.push(ele);
}
roots = cy.collection(rootsArray);
} else if (is.string(options.roots)) {
roots = cy.$(options.roots);
} else {
if (options.directed) {
roots = nodes.roots();
} else {
var components = [];
var unhandledNodes = nodes;
var _loop = function _loop() {
var currComp = cy.collection();
eles.bfs({
roots: unhandledNodes[0],
visit: function visit(node, edge, pNode, i, depth) {
currComp = currComp.add(node);
},
directed: false
});
unhandledNodes = unhandledNodes.not(currComp);
components.push(currComp);
};
while (unhandledNodes.length > 0) {
_loop();
}
roots = cy.collection();
var _loop2 = function _loop2(_i) {
var comp = components[_i];
var maxDegree = comp.maxDegree(false);
var compRoots = comp.filter(function (ele) {
return ele.degree(false) === maxDegree;
});
roots = roots.add(compRoots);
};
for (var _i = 0; _i < components.length; _i++) {
_loop2(_i);
}
}
}
var depths = [];
var foundByBfs = {};
var id2depth = {};
var prevNode = {};
var prevEdge = {};
var successors = {};
// find the depths of the nodes
graph.bfs({
roots: roots,
directed: options.directed,
visit: function visit(node, edge, pNode, i, depth) {
var ele = node[0];
var id = ele.id();
if (!depths[depth]) {
depths[depth] = [];
}
depths[depth].push(ele);
foundByBfs[id] = true;
id2depth[id] = depth;
prevNode[id] = pNode;
prevEdge[id] = edge;
if (pNode) {
var prevId = pNode.id();
var succ = successors[prevId] = successors[prevId] || [];
succ.push(node);
}
}
});
// check for nodes not found by bfs
var orphanNodes = [];
for (var _i2 = 0; _i2 < nodes.length; _i2++) {
var _ele = nodes[_i2];
if (foundByBfs[_ele.id()]) {
continue;
} else {
orphanNodes.push(_ele);
}
}
// assign orphan nodes a depth from their neighborhood
var maxChecks = orphanNodes.length * 3;
var checks = 0;
while (orphanNodes.length !== 0 && checks < maxChecks) {
var node = orphanNodes.shift();
var neighbors = node.neighborhood().nodes();
var assignedDepth = false;
for (var _i3 = 0; _i3 < neighbors.length; _i3++) {
var depth = id2depth[neighbors[_i3].id()];
if (depth !== undefined) {
depths[depth].push(node);
assignedDepth = true;
break;
}
}
if (!assignedDepth) {
orphanNodes.push(node);
}
checks++;
}
// assign orphan nodes that are still left to the depth of their subgraph
while (orphanNodes.length !== 0) {
var _node = orphanNodes.shift();
//let subgraph = graph.bfs( node ).path;
var _assignedDepth = false;
// for( let i = 0; i < subgraph.length; i++ ){
// let depth = id2depth[ subgraph[i].id() ];
// if( depth !== undefined ){
// depths[depth].push( node );
// assignedDepth = true;
// break;
// }
// }
if (!_assignedDepth) {
// worst case if the graph really isn't tree friendly, then just dump it in 0
if (depths.length === 0) {
depths.push([]);
}
depths[0].push(_node);
}
}
// assign the nodes a depth and index
var assignDepthsToEles = function assignDepthsToEles() {
for (var _i4 = 0; _i4 < depths.length; _i4++) {
var _eles = depths[_i4];
for (var j = 0; j < _eles.length; j++) {
var _ele2 = _eles[j];
if (_ele2 == null) {
_eles.splice(j, 1);
j--;
continue;
}
_ele2._private.scratch.breadthfirst = {
depth: _i4,
index: j
};
}
}
};
assignDepthsToEles();
var intersectsDepth = function intersectsDepth(node) {
// returns true if has edges pointing in from a higher depth
var edges = node.connectedEdges(function (ele) {
return ele.data('target') === node.id();
});
var thisInfo = node._private.scratch.breadthfirst;
var highestDepthOfOther = 0;
var highestOther = void 0;
for (var _i5 = 0; _i5 < edges.length; _i5++) {
var edge = edges[_i5];
var otherNode = edge.source()[0];
var otherInfo = otherNode._private.scratch.breadthfirst;
if (thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth) {
highestDepthOfOther = otherInfo.depth;
highestOther = otherNode;
}
}
return highestOther;
};
// make maximal if so set by adjusting depths
for (var adj = 0; adj < options.maximalAdjustments; adj++) {
var nDepths = depths.length;
var elesToMove = [];
for (var _i6 = 0; _i6 < nDepths; _i6++) {
var _depth = depths[_i6];
var nDepth = _depth.length;
for (var j = 0; j < nDepth; j++) {
var _ele3 = _depth[j];
var info = _ele3._private.scratch.breadthfirst;
var intEle = intersectsDepth(_ele3);
if (intEle) {
info.intEle = intEle;
elesToMove.push(_ele3);
}
}
}
for (var _i7 = 0; _i7 < elesToMove.length; _i7++) {
var _ele4 = elesToMove[_i7];
var _info = _ele4._private.scratch.breadthfirst;
var _intEle = _info.intEle;
var intInfo = _intEle._private.scratch.breadthfirst;
depths[_info.depth][_info.index] = null; // remove from old depth & index (create hole to be cleaned)
// add to end of new depth
var newDepth = intInfo.depth + 1;
while (newDepth > depths.length - 1) {
depths.push([]);
}
depths[newDepth].push(_ele4);
_info.depth = newDepth;
_info.index = depths[newDepth].length - 1;
}
assignDepthsToEles();
}
// find min distance we need to leave between nodes
var minDistance = 0;
if (options.avoidOverlap) {
for (var _i8 = 0; _i8 < nodes.length; _i8++) {
var n = nodes[_i8];
var nbb = n.layoutDimensions(options);
var w = nbb.w;
var h = nbb.h;
minDistance = Math.max(minDistance, w, h);
}
}
// get the weighted percent for an element based on its connectivity to other levels
var cachedWeightedPercent = {};
var getWeightedPercent = function getWeightedPercent(ele) {
if (cachedWeightedPercent[ele.id()]) {
return cachedWeightedPercent[ele.id()];
}
var eleDepth = ele._private.scratch.breadthfirst.depth;
var neighbors = ele.neighborhood().nodes().not(':parent').intersection(nodes);
var percent = 0;
var samples = 0;
for (var _i9 = 0; _i9 < neighbors.length; _i9++) {
var neighbor = neighbors[_i9];
var bf = neighbor._private.scratch.breadthfirst;
var index = bf.index;
var _depth2 = bf.depth;
var _nDepth = depths[_depth2].length;
if (eleDepth > _depth2 || eleDepth === 0) {
// only get influenced by elements above
percent += index / _nDepth;
samples++;
}
}
samples = Math.max(1, samples);
percent = percent / samples;
if (samples === 0) {
// so lone nodes have a "don't care" state in sorting
percent = undefined;
}
cachedWeightedPercent[ele.id()] = percent;
return percent;
};
// rearrange the indices in each depth level based on connectivity
var sortFn = function sortFn(a, b) {
var apct = getWeightedPercent(a);
var bpct = getWeightedPercent(b);
return apct - bpct;
};
for (var times = 0; times < 3; times++) {
// do it a few times b/c the depths are dynamic and we want a more stable result
for (var _i10 = 0; _i10 < depths.length; _i10++) {
depths[_i10] = depths[_i10].sort(sortFn);
}
assignDepthsToEles(); // and update
}
var biggestDepthSize = 0;
for (var _i11 = 0; _i11 < depths.length; _i11++) {
biggestDepthSize = Math.max(depths[_i11].length, biggestDepthSize);
}
var center = {
x: bb.x1 + bb.w / 2,
y: bb.x1 + bb.h / 2
};
var getPosition = function getPosition(ele, isBottomDepth) {
var info = ele._private.scratch.breadthfirst;
var depth = info.depth;
var index = info.index;
var depthSize = depths[depth].length;
var distanceX = Math.max(bb.w / (depthSize + 1), minDistance);
var distanceY = Math.max(bb.h / (depths.length + 1), minDistance);
var radiusStepSize = Math.min(bb.w / 2 / depths.length, bb.h / 2 / depths.length);
radiusStepSize = Math.max(radiusStepSize, minDistance);
if (!options.circle) {
var epos = {
x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX,
y: (depth + 1) * distanceY
};
if (isBottomDepth) {
return epos;
}
// let succs = successors[ ele.id() ];
// if( succs ){
// epos.x = 0;
//
// for( let i = 0 ; i < succs.length; i++ ){
// let spos = pos[ succs[i].id() ];
//
// epos.x += spos.x;
// }
//
// epos.x /= succs.length;
// } else {
// //debugger;
// }
return epos;
} else {
if (options.circle) {
var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize / 2 : 0);
var theta = 2 * Math.PI / depths[depth].length * index;
if (depth === 0 && depths[0].length === 1) {
radius = 1;
}
return {
x: center.x + radius * Math.cos(theta),
y: center.y + radius * Math.sin(theta)
};
} else {
return {
x: center.x + (index + 1 - (depthSize + 1) / 2) * distanceX,
y: (depth + 1) * distanceY
};
}
}
};
// get positions in reverse depth order
var pos = {};
for (var _i12 = depths.length - 1; _i12 >= 0; _i12--) {
var _depth3 = depths[_i12];
for (var _j = 0; _j < _depth3.length; _j++) {
var _node2 = _depth3[_j];
pos[_node2.id()] = getPosition(_node2, _i12 === depths.length - 1);
}
}
nodes.layoutPositions(this, options, function (node) {
return pos[node.id()];
});
return this; // chaining
};
module.exports = BreadthFirstLayout;
/***/ }),
/* 99 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var defaults = {
fit: true, // whether to fit the viewport to the graph
padding: 30, // the padding on fit
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
radius: undefined, // the radius of the circle
startAngle: 3 / 2 * Math.PI, // where nodes start in radians
sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)
clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)
sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function CircleLayout(options) {
this.options = util.extend({}, defaults, options);
}
CircleLayout.prototype.run = function () {
var params = this.options;
var options = params;
var cy = params.cy;
var eles = options.eles;
var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;
var nodes = eles.nodes().not(':parent');
if (options.sort) {
nodes = nodes.sort(options.sort);
}
var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
});
var center = {
x: bb.x1 + bb.w / 2,
y: bb.y1 + bb.h / 2
};
var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / nodes.length : options.sweep;
var dTheta = sweep / Math.max(1, nodes.length - 1);
var r = void 0;
var minDistance = 0;
for (var i = 0; i < nodes.length; i++) {
var n = nodes[i];
var nbb = n.layoutDimensions(options);
var w = nbb.w;
var h = nbb.h;
minDistance = Math.max(minDistance, w, h);
}
if (is.number(options.radius)) {
r = options.radius;
} else if (nodes.length <= 1) {
r = 0;
} else {
r = Math.min(bb.h, bb.w) / 2 - minDistance;
}
// calculate the radius
if (nodes.length > 1 && options.avoidOverlap) {
// but only if more than one node (can't overlap)
minDistance *= 1.75; // just to have some nice spacing
var dcos = Math.cos(dTheta) - Math.cos(0);
var dsin = Math.sin(dTheta) - Math.sin(0);
var rMin = Math.sqrt(minDistance * minDistance / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping
r = Math.max(rMin, r);
}
var getPos = function getPos(ele, i) {
var theta = options.startAngle + i * dTheta * (clockwise ? 1 : -1);
var rx = r * Math.cos(theta);
var ry = r * Math.sin(theta);
var pos = {
x: center.x + rx,
y: center.y + ry
};
return pos;
};
nodes.layoutPositions(this, options, getPos);
return this; // chaining
};
module.exports = CircleLayout;
/***/ }),
/* 100 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var defaults = {
fit: true, // whether to fit the viewport to the graph
padding: 30, // the padding on fit
startAngle: 3 / 2 * Math.PI, // where nodes start in radians
sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)
clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)
equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow
minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment)
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
height: undefined, // height of layout area (overrides container height)
width: undefined, // width of layout area (overrides container width)
spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
concentric: function concentric(node) {
// returns numeric value for each node, placing higher nodes in levels towards the centre
return node.degree();
},
levelWidth: function levelWidth(nodes) {
// the letiation of concentric values in each level
return nodes.maxDegree() / 4;
},
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function ConcentricLayout(options) {
this.options = util.extend({}, defaults, options);
}
ConcentricLayout.prototype.run = function () {
var params = this.options;
var options = params;
var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;
var cy = params.cy;
var eles = options.eles;
var nodes = eles.nodes().not(':parent');
var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
});
var center = {
x: bb.x1 + bb.w / 2,
y: bb.y1 + bb.h / 2
};
var nodeValues = []; // { node, value }
var theta = options.startAngle;
var maxNodeSize = 0;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var value = void 0;
// calculate the node value
value = options.concentric(node);
nodeValues.push({
value: value,
node: node
});
// for style mapping
node._private.scratch.concentric = value;
}
// in case we used the `concentric` in style
nodes.updateStyle();
// calculate max size now based on potentially updated mappers
for (var _i = 0; _i < nodes.length; _i++) {
var _node = nodes[_i];
var nbb = _node.layoutDimensions(options);
maxNodeSize = Math.max(maxNodeSize, nbb.w, nbb.h);
}
// sort node values in descreasing order
nodeValues.sort(function (a, b) {
return b.value - a.value;
});
var levelWidth = options.levelWidth(nodes);
// put the values into levels
var levels = [[]];
var currentLevel = levels[0];
for (var _i2 = 0; _i2 < nodeValues.length; _i2++) {
var val = nodeValues[_i2];
if (currentLevel.length > 0) {
var diff = Math.abs(currentLevel[0].value - val.value);
if (diff >= levelWidth) {
currentLevel = [];
levels.push(currentLevel);
}
}
currentLevel.push(val);
}
// create positions from levels
var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes
if (!options.avoidOverlap) {
// then strictly constrain to bb
var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;
var maxR = Math.min(bb.w, bb.h) / 2 - minDist;
var rStep = maxR / (levels.length + firstLvlHasMulti ? 1 : 0);
minDist = Math.min(minDist, rStep);
}
// find the metrics for each level
var r = 0;
for (var _i3 = 0; _i3 < levels.length; _i3++) {
var level = levels[_i3];
var sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / level.length : options.sweep;
var dTheta = level.dTheta = sweep / Math.max(1, level.length - 1);
// calculate the radius
if (level.length > 1 && options.avoidOverlap) {
// but only if more than one node (can't overlap)
var dcos = Math.cos(dTheta) - Math.cos(0);
var dsin = Math.sin(dTheta) - Math.sin(0);
var rMin = Math.sqrt(minDist * minDist / (dcos * dcos + dsin * dsin)); // s.t. no nodes overlapping
r = Math.max(rMin, r);
}
level.r = r;
r += minDist;
}
if (options.equidistant) {
var rDeltaMax = 0;
var _r = 0;
for (var _i4 = 0; _i4 < levels.length; _i4++) {
var _level = levels[_i4];
var rDelta = _level.r - _r;
rDeltaMax = Math.max(rDeltaMax, rDelta);
}
_r = 0;
for (var _i5 = 0; _i5 < levels.length; _i5++) {
var _level2 = levels[_i5];
if (_i5 === 0) {
_r = _level2.r;
}
_level2.r = _r;
_r += rDeltaMax;
}
}
// calculate the node positions
var pos = {}; // id => position
for (var _i6 = 0; _i6 < levels.length; _i6++) {
var _level3 = levels[_i6];
var _dTheta = _level3.dTheta;
var _r2 = _level3.r;
for (var j = 0; j < _level3.length; j++) {
var _val = _level3[j];
var _theta = options.startAngle + (clockwise ? 1 : -1) * _dTheta * j;
var p = {
x: center.x + _r2 * Math.cos(_theta),
y: center.y + _r2 * Math.sin(_theta)
};
pos[_val.node.id()] = p;
}
}
// position the nodes
nodes.layoutPositions(this, options, function (ele) {
var id = ele.id();
return pos[id];
});
return this; // chaining
};
module.exports = ConcentricLayout;
/***/ }),
/* 101 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*
The CoSE layout was written by Gerardo Huck.
https://www.linkedin.com/in/gerardohuck/
Based on the following article:
http://dl.acm.org/citation.cfm?id=1498047
Modifications tracked on Github.
*/
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var Promise = __webpack_require__(5);
var DEBUG;
/**
* @brief : default layout options
*/
var defaults = {
// Called on `layoutready`
ready: function ready() {},
// Called on `layoutstop`
stop: function stop() {},
// Whether to animate while running the layout
// true : Animate continuously as the layout is running
// false : Just show the end result
// 'end' : Animate with the end result, from the initial positions to the end positions
animate: true,
// Easing of the animation for animate:'end'
animationEasing: undefined,
// The duration of the animation for animate:'end'
animationDuration: undefined,
// A function that determines whether the node should be animated
// All nodes animated by default on animate enabled
// Non-animated nodes are positioned immediately when the layout starts
animateFilter: function animateFilter(node, i) {
return true;
},
// The layout animates only after this many milliseconds for animate:true
// (prevents flashing on fast runs)
animationThreshold: 250,
// Number of iterations between consecutive screen positions update
// (0 -> only updated on the end)
refresh: 20,
// Whether to fit the network view after when done
fit: true,
// Padding on fit
padding: 30,
// Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
boundingBox: undefined,
// Excludes the label when calculating node bounding boxes for the layout algorithm
nodeDimensionsIncludeLabels: false,
// Randomize the initial positions of the nodes (true) or use existing positions (false)
randomize: false,
// Extra spacing between components in non-compound graphs
componentSpacing: 40,
// Node repulsion (non overlapping) multiplier
nodeRepulsion: function nodeRepulsion(node) {
return 2048;
},
// Node repulsion (overlapping) multiplier
nodeOverlap: 4,
// Ideal edge (non nested) length
idealEdgeLength: function idealEdgeLength(edge) {
return 32;
},
// Divisor to compute edge forces
edgeElasticity: function edgeElasticity(edge) {
return 32;
},
// Nesting factor (multiplier) to compute ideal edge length for nested edges
nestingFactor: 1.2,
// Gravity force (constant)
gravity: 1,
// Maximum number of iterations to perform
numIter: 1000,
// Initial temperature (maximum node displacement)
initialTemp: 1000,
// Cooling factor (how the temperature is reduced between consecutive iterations
coolingFactor: 0.99,
// Lower temperature threshold (below this point the layout will end)
minTemp: 1.0,
// Pass a reference to weaver to use threads for calculations
weaver: false
};
/**
* @brief : constructor
* @arg options : object containing layout options
*/
function CoseLayout(options) {
this.options = util.extend({}, defaults, options);
this.options.layout = this;
}
/**
* @brief : runs the layout
*/
CoseLayout.prototype.run = function () {
var options = this.options;
var cy = options.cy;
var layout = this;
var thread = this.thread;
var Thread = options.weaver ? options.weaver.Thread : null;
var falseThread = { // use false thread as polyfill
listeners: [],
on: function on(e, cb) {
this.listeners.push({ event: e, callback: cb });
return this;
},
trigger: function trigger(e) {
if (is.string(e)) {
e = { type: e };
}
var matchesEvent = function matchesEvent(l) {
return l.event === e.type;
};
var trigger = function trigger(l) {
l.callback(e);
};
this.listeners.filter(matchesEvent).forEach(trigger);
return this;
},
pass: function pass(data) {
this.pass = data;
return this;
},
run: function run(cb) {
var pass = this.pass;
return new Promise(function (resolve) {
resolve(cb(pass));
});
},
stop: function stop() {
return this;
},
stopped: function stopped() {
return true;
}
};
function broadcast(message) {
// for false thread
var e = { type: 'message', message: message };
falseThread.trigger(e);
}
if (!thread || thread.stopped()) {
thread = this.thread = Thread ? new Thread() : falseThread;
}
layout.stopped = false;
if (options.animate === true || options.animate === false) {
layout.emit({ type: 'layoutstart', layout: layout });
}
// Set DEBUG - Global variable
if (true === options.debug) {
DEBUG = true;
} else {
DEBUG = false;
}
// Initialize layout info
var layoutInfo = createLayoutInfo(cy, layout, options);
// Show LayoutInfo contents if debugging
if (DEBUG) {
printLayoutInfo(layoutInfo);
}
// If required, randomize node positions
if (options.randomize) {
randomizePositions(layoutInfo, cy);
}
var startTime = Date.now();
var refreshRequested = false;
var refresh = function refresh(rOpts) {
rOpts = rOpts || {};
if (refreshRequested && !rOpts.next) {
return;
}
if (!rOpts.force && Date.now() - startTime < options.animationThreshold) {
return;
}
refreshRequested = true;
util.requestAnimationFrame(function () {
refreshPositions(layoutInfo, cy, options);
// Fit the graph if necessary
if (true === options.fit) {
cy.fit(options.padding);
}
refreshRequested = false;
if (rOpts.next) {
rOpts.next();
}
});
};
thread.on('message', function (e) {
var layoutNodes = e.message;
layoutInfo.layoutNodes = layoutNodes;
refresh();
});
thread.pass({
layoutInfo: layoutInfo,
options: {
animate: options.animate,
refresh: options.refresh,
componentSpacing: options.componentSpacing,
nodeOverlap: options.nodeOverlap,
nestingFactor: options.nestingFactor,
gravity: options.gravity,
numIter: options.numIter,
initialTemp: options.initialTemp,
coolingFactor: options.coolingFactor,
minTemp: options.minTemp
}
}).run(function (pass) {
var layoutInfo = pass.layoutInfo;
var options = pass.options;
var stopped = false;
/**
* @brief : Performs one iteration of the physical simulation
* @arg layoutInfo : LayoutInfo object already initialized
* @arg cy : Cytoscape object
* @arg options : Layout options
*/
var step = function step(layoutInfo, options, _step) {
// var s = "\n\n###############################";
// s += "\nSTEP: " + step;
// s += "\n###############################\n";
// logDebug(s);
// Calculate node repulsions
calculateNodeForces(layoutInfo, options);
// Calculate edge forces
calculateEdgeForces(layoutInfo, options);
// Calculate gravity forces
calculateGravityForces(layoutInfo, options);
// Propagate forces from parent to child
propagateForces(layoutInfo, options);
// Update positions based on calculated forces
updatePositions(layoutInfo, options);
};
/**
* @brief : Computes the node repulsion forces
*/
var calculateNodeForces = function calculateNodeForces(layoutInfo, options) {
// Go through each of the graphs in graphSet
// Nodes only repel each other if they belong to the same graph
// var s = 'calculateNodeForces';
// logDebug(s);
for (var i = 0; i < layoutInfo.graphSet.length; i++) {
var graph = layoutInfo.graphSet[i];
var numNodes = graph.length;
// s = "Set: " + graph.toString();
// logDebug(s);
// Now get all the pairs of nodes
// Only get each pair once, (A, B) = (B, A)
for (var j = 0; j < numNodes; j++) {
var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];
for (var k = j + 1; k < numNodes; k++) {
var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];
nodeRepulsion(node1, node2, layoutInfo, options);
}
}
}
};
var randomDistance = function randomDistance(max) {
return -max + 2 * max * Math.random();
};
/**
* @brief : Compute the node repulsion forces between a pair of nodes
*/
var nodeRepulsion = function nodeRepulsion(node1, node2, layoutInfo, options) {
// var s = "Node repulsion. Node1: " + node1.id + " Node2: " + node2.id;
var cmptId1 = node1.cmptId;
var cmptId2 = node2.cmptId;
if (cmptId1 !== cmptId2 && !layoutInfo.isCompound) {
return;
}
// Get direction of line connecting both node centers
var directionX = node2.positionX - node1.positionX;
var directionY = node2.positionY - node1.positionY;
var maxRandDist = 1;
// s += "\ndirectionX: " + directionX + ", directionY: " + directionY;
// If both centers are the same, apply a random force
if (0 === directionX && 0 === directionY) {
directionX = randomDistance(maxRandDist);
directionY = randomDistance(maxRandDist);
}
var overlap = nodesOverlap(node1, node2, directionX, directionY);
if (overlap > 0) {
// s += "\nNodes DO overlap.";
// s += "\nOverlap: " + overlap;
// If nodes overlap, repulsion force is proportional
// to the overlap
var force = options.nodeOverlap * overlap;
// Compute the module and components of the force vector
var distance = Math.sqrt(directionX * directionX + directionY * directionY);
// s += "\nDistance: " + distance;
var forceX = force * directionX / distance;
var forceY = force * directionY / distance;
} else {
// s += "\nNodes do NOT overlap.";
// If there's no overlap, force is inversely proportional
// to squared distance
// Get clipping points for both nodes
var point1 = findClippingPoint(node1, directionX, directionY);
var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY);
// Use clipping points to compute distance
var distanceX = point2.x - point1.x;
var distanceY = point2.y - point1.y;
var distanceSqr = distanceX * distanceX + distanceY * distanceY;
var distance = Math.sqrt(distanceSqr);
// s += "\nDistance: " + distance;
// Compute the module and components of the force vector
var force = (node1.nodeRepulsion + node2.nodeRepulsion) / distanceSqr;
var forceX = force * distanceX / distance;
var forceY = force * distanceY / distance;
}
// Apply force
if (!node1.isLocked) {
node1.offsetX -= forceX;
node1.offsetY -= forceY;
}
if (!node2.isLocked) {
node2.offsetX += forceX;
node2.offsetY += forceY;
}
// s += "\nForceX: " + forceX + " ForceY: " + forceY;
// logDebug(s);
return;
};
/**
* @brief : Determines whether two nodes overlap or not
* @return : Amount of overlapping (0 => no overlap)
*/
var nodesOverlap = function nodesOverlap(node1, node2, dX, dY) {
if (dX > 0) {
var overlapX = node1.maxX - node2.minX;
} else {
var overlapX = node2.maxX - node1.minX;
}
if (dY > 0) {
var overlapY = node1.maxY - node2.minY;
} else {
var overlapY = node2.maxY - node1.minY;
}
if (overlapX >= 0 && overlapY >= 0) {
return Math.sqrt(overlapX * overlapX + overlapY * overlapY);
} else {
return 0;
}
};
/**
* @brief : Finds the point in which an edge (direction dX, dY) intersects
* the rectangular bounding box of it's source/target node
*/
var findClippingPoint = function findClippingPoint(node, dX, dY) {
// Shorcuts
var X = node.positionX;
var Y = node.positionY;
var H = node.height || 1;
var W = node.width || 1;
var dirSlope = dY / dX;
var nodeSlope = H / W;
// var s = 'Computing clipping point of node ' + node.id +
// " . Height: " + H + ", Width: " + W +
// "\nDirection " + dX + ", " + dY;
//
// Compute intersection
var res = {};
// Case: Vertical direction (up)
if (0 === dX && 0 < dY) {
res.x = X;
// s += "\nUp direction";
res.y = Y + H / 2;
return res;
}
// Case: Vertical direction (down)
if (0 === dX && 0 > dY) {
res.x = X;
res.y = Y + H / 2;
// s += "\nDown direction";
return res;
}
// Case: Intersects the right border
if (0 < dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) {
res.x = X + W / 2;
res.y = Y + W * dY / 2 / dX;
// s += "\nRightborder";
return res;
}
// Case: Intersects the left border
if (0 > dX && -1 * nodeSlope <= dirSlope && dirSlope <= nodeSlope) {
res.x = X - W / 2;
res.y = Y - W * dY / 2 / dX;
// s += "\nLeftborder";
return res;
}
// Case: Intersects the top border
if (0 < dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) {
res.x = X + H * dX / 2 / dY;
res.y = Y + H / 2;
// s += "\nTop border";
return res;
}
// Case: Intersects the bottom border
if (0 > dY && (dirSlope <= -1 * nodeSlope || dirSlope >= nodeSlope)) {
res.x = X - H * dX / 2 / dY;
res.y = Y - H / 2;
// s += "\nBottom border";
return res;
}
// s += "\nClipping point found at " + res.x + ", " + res.y;
// logDebug(s);
return res;
};
/**
* @brief : Calculates all edge forces
*/
var calculateEdgeForces = function calculateEdgeForces(layoutInfo, options) {
// Iterate over all edges
for (var i = 0; i < layoutInfo.edgeSize; i++) {
// Get edge, source & target nodes
var edge = layoutInfo.layoutEdges[i];
var sourceIx = layoutInfo.idToIndex[edge.sourceId];
var source = layoutInfo.layoutNodes[sourceIx];
var targetIx = layoutInfo.idToIndex[edge.targetId];
var target = layoutInfo.layoutNodes[targetIx];
// Get direction of line connecting both node centers
var directionX = target.positionX - source.positionX;
var directionY = target.positionY - source.positionY;
// If both centers are the same, do nothing.
// A random force has already been applied as node repulsion
if (0 === directionX && 0 === directionY) {
continue;
}
// Get clipping points for both nodes
var point1 = findClippingPoint(source, directionX, directionY);
var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);
var lx = point2.x - point1.x;
var ly = point2.y - point1.y;
var l = Math.sqrt(lx * lx + ly * ly);
var force = Math.pow(edge.idealLength - l, 2) / edge.elasticity;
if (0 !== l) {
var forceX = force * lx / l;
var forceY = force * ly / l;
} else {
var forceX = 0;
var forceY = 0;
}
// Add this force to target and source nodes
if (!source.isLocked) {
source.offsetX += forceX;
source.offsetY += forceY;
}
if (!target.isLocked) {
target.offsetX -= forceX;
target.offsetY -= forceY;
}
// var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;
// s += "\nDistance: " + l + " Force: (" + forceX + ", " + forceY + ")";
// logDebug(s);
}
};
/**
* @brief : Computes gravity forces for all nodes
*/
var calculateGravityForces = function calculateGravityForces(layoutInfo, options) {
var distThreshold = 1;
// var s = 'calculateGravityForces';
// logDebug(s);
for (var i = 0; i < layoutInfo.graphSet.length; i++) {
var graph = layoutInfo.graphSet[i];
var numNodes = graph.length;
// s = "Set: " + graph.toString();
// logDebug(s);
// Compute graph center
if (0 === i) {
var centerX = layoutInfo.clientHeight / 2;
var centerY = layoutInfo.clientWidth / 2;
} else {
// Get Parent node for this graph, and use its position as center
var temp = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];
var parent = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];
var centerX = parent.positionX;
var centerY = parent.positionY;
}
// s = "Center found at: " + centerX + ", " + centerY;
// logDebug(s);
// Apply force to all nodes in graph
for (var j = 0; j < numNodes; j++) {
var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];
// s = "Node: " + node.id;
if (node.isLocked) {
continue;
}
var dx = centerX - node.positionX;
var dy = centerY - node.positionY;
var d = Math.sqrt(dx * dx + dy * dy);
if (d > distThreshold) {
var fx = options.gravity * dx / d;
var fy = options.gravity * dy / d;
node.offsetX += fx;
node.offsetY += fy;
// s += ": Applied force: " + fx + ", " + fy;
} else {}
// s += ": skypped since it's too close to center";
// logDebug(s);
}
}
};
/**
* @brief : This function propagates the existing offsets from
* parent nodes to its descendents.
* @arg layoutInfo : layoutInfo Object
* @arg cy : cytoscape Object
* @arg options : Layout options
*/
var propagateForces = function propagateForces(layoutInfo, options) {
// Inline implementation of a queue, used for traversing the graph in BFS order
var queue = [];
var start = 0; // Points to the start the queue
var end = -1; // Points to the end of the queue
// logDebug('propagateForces');
// Start by visiting the nodes in the root graph
queue.push.apply(queue, layoutInfo.graphSet[0]);
end += layoutInfo.graphSet[0].length;
// Traverse the graph, level by level,
while (start <= end) {
// Get the node to visit and remove it from queue
var nodeId = queue[start++];
var nodeIndex = layoutInfo.idToIndex[nodeId];
var node = layoutInfo.layoutNodes[nodeIndex];
var children = node.children;
// We only need to process the node if it's compound
if (0 < children.length && !node.isLocked) {
var offX = node.offsetX;
var offY = node.offsetY;
// var s = "Propagating offset from parent node : " + node.id +
// ". OffsetX: " + offX + ". OffsetY: " + offY;
// s += "\n Children: " + children.toString();
// logDebug(s);
for (var i = 0; i < children.length; i++) {
var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]];
// Propagate offset
childNode.offsetX += offX;
childNode.offsetY += offY;
// Add children to queue to be visited
queue[++end] = children[i];
}
// Reset parent offsets
node.offsetX = 0;
node.offsetY = 0;
}
}
};
/**
* @brief : Updates the layout model positions, based on
* the accumulated forces
*/
var updatePositions = function updatePositions(layoutInfo, options) {
// var s = 'Updating positions';
// logDebug(s);
// Reset boundaries for compound nodes
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
if (0 < n.children.length) {
// logDebug("Resetting boundaries of compound node: " + n.id);
n.maxX = undefined;
n.minX = undefined;
n.maxY = undefined;
n.minY = undefined;
}
}
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
if (0 < n.children.length || n.isLocked) {
// No need to set compound or locked node position
// logDebug("Skipping position update of node: " + n.id);
continue;
}
// s = "Node: " + n.id + " Previous position: (" +
// n.positionX + ", " + n.positionY + ").";
// Limit displacement in order to improve stability
var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);
n.positionX += tempForce.x;
n.positionY += tempForce.y;
n.offsetX = 0;
n.offsetY = 0;
n.minX = n.positionX - n.width;
n.maxX = n.positionX + n.width;
n.minY = n.positionY - n.height;
n.maxY = n.positionY + n.height;
// s += " New Position: (" + n.positionX + ", " + n.positionY + ").";
// logDebug(s);
// Update ancestry boudaries
updateAncestryBoundaries(n, layoutInfo);
}
// Update size, position of compund nodes
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
if (0 < n.children.length && !n.isLocked) {
n.positionX = (n.maxX + n.minX) / 2;
n.positionY = (n.maxY + n.minY) / 2;
n.width = n.maxX - n.minX;
n.height = n.maxY - n.minY;
// s = "Updating position, size of compound node " + n.id;
// s += "\nPositionX: " + n.positionX + ", PositionY: " + n.positionY;
// s += "\nWidth: " + n.width + ", Height: " + n.height;
// logDebug(s);
}
}
};
/**
* @brief : Limits a force (forceX, forceY) to be not
* greater (in modulo) than max.
8 Preserves force direction.
*/
var limitForce = function limitForce(forceX, forceY, max) {
// var s = "Limiting force: (" + forceX + ", " + forceY + "). Max: " + max;
var force = Math.sqrt(forceX * forceX + forceY * forceY);
if (force > max) {
var res = {
x: max * forceX / force,
y: max * forceY / force
};
} else {
var res = {
x: forceX,
y: forceY
};
}
// s += ".\nResult: (" + res.x + ", " + res.y + ")";
// logDebug(s);
return res;
};
/**
* @brief : Function used for keeping track of compound node
* sizes, since they should bound all their subnodes.
*/
var updateAncestryBoundaries = function updateAncestryBoundaries(node, layoutInfo) {
// var s = "Propagating new position/size of node " + node.id;
var parentId = node.parentId;
if (null == parentId) {
// If there's no parent, we are done
// s += ". No parent node.";
// logDebug(s);
return;
}
// Get Parent Node
var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];
var flag = false;
// MaxX
if (null == p.maxX || node.maxX + p.padRight > p.maxX) {
p.maxX = node.maxX + p.padRight;
flag = true;
// s += "\nNew maxX for parent node " + p.id + ": " + p.maxX;
}
// MinX
if (null == p.minX || node.minX - p.padLeft < p.minX) {
p.minX = node.minX - p.padLeft;
flag = true;
// s += "\nNew minX for parent node " + p.id + ": " + p.minX;
}
// MaxY
if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {
p.maxY = node.maxY + p.padBottom;
flag = true;
// s += "\nNew maxY for parent node " + p.id + ": " + p.maxY;
}
// MinY
if (null == p.minY || node.minY - p.padTop < p.minY) {
p.minY = node.minY - p.padTop;
flag = true;
// s += "\nNew minY for parent node " + p.id + ": " + p.minY;
}
// If updated boundaries, propagate changes upward
if (flag) {
// logDebug(s);
return updateAncestryBoundaries(p, layoutInfo);
}
// s += ". No changes in boundaries/position of parent node " + p.id;
// logDebug(s);
return;
};
var separateComponents = function separateComponents(layutInfo, options) {
var nodes = layoutInfo.layoutNodes;
var components = [];
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var cid = node.cmptId;
var component = components[cid] = components[cid] || [];
component.push(node);
}
var totalA = 0;
for (var i = 0; i < components.length; i++) {
var c = components[i];
if (!c) {
continue;
}
c.x1 = Infinity;
c.x2 = -Infinity;
c.y1 = Infinity;
c.y2 = -Infinity;
for (var j = 0; j < c.length; j++) {
var n = c[j];
c.x1 = Math.min(c.x1, n.positionX - n.width / 2);
c.x2 = Math.max(c.x2, n.positionX + n.width / 2);
c.y1 = Math.min(c.y1, n.positionY - n.height / 2);
c.y2 = Math.max(c.y2, n.positionY + n.height / 2);
}
c.w = c.x2 - c.x1;
c.h = c.y2 - c.y1;
totalA += c.w * c.h;
}
components.sort(function (c1, c2) {
return c2.w * c2.h - c1.w * c1.h;
});
var x = 0;
var y = 0;
var usedW = 0;
var rowH = 0;
var maxRowW = Math.sqrt(totalA) * layoutInfo.clientWidth / layoutInfo.clientHeight;
for (var i = 0; i < components.length; i++) {
var c = components[i];
if (!c) {
continue;
}
for (var j = 0; j < c.length; j++) {
var n = c[j];
if (!n.isLocked) {
n.positionX += x;
n.positionY += y;
}
}
x += c.w + options.componentSpacing;
usedW += c.w + options.componentSpacing;
rowH = Math.max(rowH, c.h);
if (usedW > maxRowW) {
y += rowH + options.componentSpacing;
x = 0;
usedW = 0;
rowH = 0;
}
}
};
var mainLoop = function mainLoop(i) {
if (stopped) {
// logDebug("Layout manually stopped. Stopping computation in step " + i);
return false;
}
// Do one step in the phisical simulation
step(layoutInfo, options, i);
// Update temperature
layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor;
// logDebug("New temperature: " + layoutInfo.temperature);
if (layoutInfo.temperature < options.minTemp) {
// logDebug("Temperature drop below minimum threshold. Stopping computation in step " + i);
return false;
}
return true;
};
var i = 0;
var loopRet;
do {
var f = 0;
while (f < options.refresh && i < options.numIter) {
var loopRet = mainLoop(i);
if (!loopRet) {
break;
}
f++;
i++;
}
if (options.animate === true) {
broadcast(layoutInfo.layoutNodes); // eslint-disable-line no-undef
}
} while (loopRet && i + 1 < options.numIter);
separateComponents(layoutInfo, options);
return layoutInfo;
}).then(function (layoutInfoUpdated) {
layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions
thread.stop();
done();
});
var done = function done() {
if (options.animate === true || options.animate === false) {
refresh({
force: true,
next: function next() {
// Layout has finished
layout.one('layoutstop', options.stop);
layout.emit({ type: 'layoutstop', layout: layout });
}
});
} else {
options.eles.nodes().layoutPositions(layout, options, function (node) {
var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];
return { x: lnode.positionX, y: lnode.positionY };
});
}
};
return this; // chaining
};
/**
* @brief : called on continuous layouts to stop them before they finish
*/
CoseLayout.prototype.stop = function () {
this.stopped = true;
if (this.thread) {
this.thread.stop();
}
this.emit('layoutstop');
return this; // chaining
};
CoseLayout.prototype.destroy = function () {
if (this.thread) {
this.thread.stop();
}
return this; // chaining
};
/**
* @brief : Creates an object which is contains all the data
* used in the layout process
* @arg cy : cytoscape.js object
* @return : layoutInfo object initialized
*/
var createLayoutInfo = function createLayoutInfo(cy, layout, options) {
// Shortcut
var edges = options.eles.edges();
var nodes = options.eles.nodes();
var layoutInfo = {
isCompound: cy.hasCompoundNodes(),
layoutNodes: [],
idToIndex: {},
nodeSize: nodes.size(),
graphSet: [],
indexToGraph: [],
layoutEdges: [],
edgeSize: edges.size(),
temperature: options.initialTemp,
clientWidth: cy.width(),
clientHeight: cy.width(),
boundingBox: math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
})
};
var components = options.eles.components();
var id2cmptId = {};
for (var i = 0; i < components.length; i++) {
var component = components[i];
for (var j = 0; j < component.length; j++) {
var node = component[j];
id2cmptId[node.id()] = i;
}
}
// Iterate over all nodes, creating layout nodes
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = nodes[i];
var nbb = n.layoutDimensions(options);
var tempNode = {};
tempNode.isLocked = n.locked();
tempNode.id = n.data('id');
tempNode.parentId = n.data('parent');
tempNode.cmptId = id2cmptId[n.id()];
tempNode.children = [];
tempNode.positionX = n.position('x');
tempNode.positionY = n.position('y');
tempNode.offsetX = 0;
tempNode.offsetY = 0;
tempNode.height = nbb.w;
tempNode.width = nbb.h;
tempNode.maxX = tempNode.positionX + tempNode.width / 2;
tempNode.minX = tempNode.positionX - tempNode.width / 2;
tempNode.maxY = tempNode.positionY + tempNode.height / 2;
tempNode.minY = tempNode.positionY - tempNode.height / 2;
tempNode.padLeft = parseFloat(n.style('padding'));
tempNode.padRight = parseFloat(n.style('padding'));
tempNode.padTop = parseFloat(n.style('padding'));
tempNode.padBottom = parseFloat(n.style('padding'));
// forces
tempNode.nodeRepulsion = is.fn(options.nodeRepulsion) ? options.nodeRepulsion(n) : options.nodeRepulsion;
// Add new node
layoutInfo.layoutNodes.push(tempNode);
// Add entry to id-index map
layoutInfo.idToIndex[tempNode.id] = i;
}
// Inline implementation of a queue, used for traversing the graph in BFS order
var queue = [];
var start = 0; // Points to the start the queue
var end = -1; // Points to the end of the queue
var tempGraph = [];
// Second pass to add child information and
// initialize queue for hierarchical traversal
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
var p_id = n.parentId;
// Check if node n has a parent node
if (null != p_id) {
// Add node Id to parent's list of children
layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);
} else {
// If a node doesn't have a parent, then it's in the root graph
queue[++end] = n.id;
tempGraph.push(n.id);
}
}
// Add root graph to graphSet
layoutInfo.graphSet.push(tempGraph);
// Traverse the graph, level by level,
while (start <= end) {
// Get the node to visit and remove it from queue
var node_id = queue[start++];
var node_ix = layoutInfo.idToIndex[node_id];
var node = layoutInfo.layoutNodes[node_ix];
var children = node.children;
if (children.length > 0) {
// Add children nodes as a new graph to graph set
layoutInfo.graphSet.push(children);
// Add children to que queue to be visited
for (var i = 0; i < children.length; i++) {
queue[++end] = children[i];
}
}
}
// Create indexToGraph map
for (var i = 0; i < layoutInfo.graphSet.length; i++) {
var graph = layoutInfo.graphSet[i];
for (var j = 0; j < graph.length; j++) {
var index = layoutInfo.idToIndex[graph[j]];
layoutInfo.indexToGraph[index] = i;
}
}
// Iterate over all edges, creating Layout Edges
for (var i = 0; i < layoutInfo.edgeSize; i++) {
var e = edges[i];
var tempEdge = {};
tempEdge.id = e.data('id');
tempEdge.sourceId = e.data('source');
tempEdge.targetId = e.data('target');
// Compute ideal length
var idealLength = is.fn(options.idealEdgeLength) ? options.idealEdgeLength(e) : options.idealEdgeLength;
var elasticity = is.fn(options.edgeElasticity) ? options.edgeElasticity(e) : options.edgeElasticity;
// Check if it's an inter graph edge
var sourceIx = layoutInfo.idToIndex[tempEdge.sourceId];
var targetIx = layoutInfo.idToIndex[tempEdge.targetId];
var sourceGraph = layoutInfo.indexToGraph[sourceIx];
var targetGraph = layoutInfo.indexToGraph[targetIx];
if (sourceGraph != targetGraph) {
// Find lowest common graph ancestor
var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo);
// Compute sum of node depths, relative to lca graph
var lcaGraph = layoutInfo.graphSet[lca];
var depth = 0;
// Source depth
var tempNode = layoutInfo.layoutNodes[sourceIx];
while (-1 === lcaGraph.indexOf(tempNode.id)) {
tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];
depth++;
}
// Target depth
tempNode = layoutInfo.layoutNodes[targetIx];
while (-1 === lcaGraph.indexOf(tempNode.id)) {
tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];
depth++;
}
// logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +
// ". Index: " + lca + " Contents: " + lcaGraph.toString() +
// ". Depth: " + depth);
// Update idealLength
idealLength *= depth * options.nestingFactor;
}
tempEdge.idealLength = idealLength;
tempEdge.elasticity = elasticity;
layoutInfo.layoutEdges.push(tempEdge);
}
// Finally, return layoutInfo object
return layoutInfo;
};
/**
* @brief : This function finds the index of the lowest common
* graph ancestor between 2 nodes in the subtree
* (from the graph hierarchy induced tree) whose
* root is graphIx
*
* @arg node1: node1's ID
* @arg node2: node2's ID
* @arg layoutInfo: layoutInfo object
*
*/
var findLCA = function findLCA(node1, node2, layoutInfo) {
// Find their common ancester, starting from the root graph
var res = findLCA_aux(node1, node2, 0, layoutInfo);
if (2 > res.count) {
// If aux function couldn't find the common ancester,
// then it is the root graph
return 0;
} else {
return res.graph;
}
};
/**
* @brief : Auxiliary function used for LCA computation
*
* @arg node1 : node1's ID
* @arg node2 : node2's ID
* @arg graphIx : subgraph index
* @arg layoutInfo : layoutInfo object
*
* @return : object of the form {count: X, graph: Y}, where:
* X is the number of ancesters (max: 2) found in
* graphIx (and it's subgraphs),
* Y is the graph index of the lowest graph containing
* all X nodes
*/
var findLCA_aux = function findLCA_aux(node1, node2, graphIx, layoutInfo) {
var graph = layoutInfo.graphSet[graphIx];
// If both nodes belongs to graphIx
if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {
return { count: 2, graph: graphIx };
}
// Make recursive calls for all subgraphs
var c = 0;
for (var i = 0; i < graph.length; i++) {
var nodeId = graph[i];
var nodeIx = layoutInfo.idToIndex[nodeId];
var children = layoutInfo.layoutNodes[nodeIx].children;
// If the node has no child, skip it
if (0 === children.length) {
continue;
}
var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];
var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);
if (0 === result.count) {
// Neither node1 nor node2 are present in this subgraph
continue;
} else if (1 === result.count) {
// One of (node1, node2) is present in this subgraph
c++;
if (2 === c) {
// We've already found both nodes, no need to keep searching
break;
}
} else {
// Both nodes are present in this subgraph
return result;
}
}
return { count: c, graph: graphIx };
};
/**
* @brief: printsLayoutInfo into js console
* Only used for debbuging
*/
var printLayoutInfo = function printLayoutInfo(layoutInfo) {
/* eslint-disable */
if (!DEBUG) {
return;
}
console.debug('layoutNodes:');
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
var s = '\nindex: ' + i + '\nId: ' + n.id + '\nChildren: ' + n.children.toString() + '\nparentId: ' + n.parentId + '\npositionX: ' + n.positionX + '\npositionY: ' + n.positionY + '\nOffsetX: ' + n.offsetX + '\nOffsetY: ' + n.offsetY + '\npadLeft: ' + n.padLeft + '\npadRight: ' + n.padRight + '\npadTop: ' + n.padTop + '\npadBottom: ' + n.padBottom;
console.debug(s);
}
console.debug('idToIndex');
for (var i in layoutInfo.idToIndex) {
console.debug('Id: ' + i + '\nIndex: ' + layoutInfo.idToIndex[i]);
}
console.debug('Graph Set');
var set = layoutInfo.graphSet;
for (var i = 0; i < set.length; i++) {
console.debug('Set : ' + i + ': ' + set[i].toString());
}
var s = 'IndexToGraph';
for (var i = 0; i < layoutInfo.indexToGraph.length; i++) {
s += '\nIndex : ' + i + ' Graph: ' + layoutInfo.indexToGraph[i];
}
console.debug(s);
s = 'Layout Edges';
for (var i = 0; i < layoutInfo.layoutEdges.length; i++) {
var e = layoutInfo.layoutEdges[i];
s += '\nEdge Index: ' + i + ' ID: ' + e.id + ' SouceID: ' + e.sourceId + ' TargetId: ' + e.targetId + ' Ideal Length: ' + e.idealLength;
}
console.debug(s);
s = 'nodeSize: ' + layoutInfo.nodeSize;
s += '\nedgeSize: ' + layoutInfo.edgeSize;
s += '\ntemperature: ' + layoutInfo.temperature;
console.debug(s);
return;
/* eslint-enable */
};
/**
* @brief : Randomizes the position of all nodes
*/
var randomizePositions = function randomizePositions(layoutInfo, cy) {
var width = layoutInfo.clientWidth;
var height = layoutInfo.clientHeight;
for (var i = 0; i < layoutInfo.nodeSize; i++) {
var n = layoutInfo.layoutNodes[i];
// No need to randomize compound nodes or locked nodes
if (0 === n.children.length && !n.isLocked) {
n.positionX = Math.random() * width;
n.positionY = Math.random() * height;
}
}
};
/**
* @brief : Updates the positions of nodes in the network
* @arg layoutInfo : LayoutInfo object
* @arg cy : Cytoscape object
* @arg options : Layout options
*/
var refreshPositions = function refreshPositions(layoutInfo, cy, options) {
// var s = 'Refreshing positions';
// logDebug(s);
var layout = options.layout;
var nodes = options.eles.nodes();
var bb = layoutInfo.boundingBox;
var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };
if (options.boundingBox) {
nodes.forEach(function (node) {
var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];
coseBB.x1 = Math.min(coseBB.x1, lnode.positionX);
coseBB.x2 = Math.max(coseBB.x2, lnode.positionX);
coseBB.y1 = Math.min(coseBB.y1, lnode.positionY);
coseBB.y2 = Math.max(coseBB.y2, lnode.positionY);
});
coseBB.w = coseBB.x2 - coseBB.x1;
coseBB.h = coseBB.y2 - coseBB.y1;
}
nodes.positions(function (ele, i) {
var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];
// s = "Node: " + lnode.id + ". Refreshed position: (" +
// lnode.positionX + ", " + lnode.positionY + ").";
// logDebug(s);
if (options.boundingBox) {
// then add extra bounding box constraint
var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;
var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;
return {
x: bb.x1 + pctX * bb.w,
y: bb.y1 + pctY * bb.h
};
} else {
return {
x: lnode.positionX,
y: lnode.positionY
};
}
});
// Trigger layoutReady only on first call
if (true !== layoutInfo.ready) {
// s = 'Triggering layoutready';
// logDebug(s);
layoutInfo.ready = true;
layout.one('layoutready', options.ready);
layout.emit({ type: 'layoutready', layout: this });
}
};
/**
* @brief : Logs a debug message in JS console, if DEBUG is ON
*/
// var logDebug = function(text) {
// if (DEBUG) {
// console.debug(text);
// }
// };
module.exports = CoseLayout;
/***/ }),
/* 102 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var defaults = {
fit: true, // whether to fit the viewport to the graph
padding: 30, // padding used on fit
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true
nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm
spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
condense: false, // uses all available space on false, uses minimal space on true
rows: undefined, // force num of rows in the grid
cols: undefined, // force num of columns in the grid
position: function position(node) {}, // returns { row, col } for element
sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function GridLayout(options) {
this.options = util.extend({}, defaults, options);
}
GridLayout.prototype.run = function () {
var params = this.options;
var options = params;
var cy = params.cy;
var eles = options.eles;
var nodes = eles.nodes().not(':parent');
if (options.sort) {
nodes = nodes.sort(options.sort);
}
var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
});
if (bb.h === 0 || bb.w === 0) {
nodes.layoutPositions(this, options, function (ele) {
return { x: bb.x1, y: bb.y1 };
});
} else {
// width/height * splits^2 = cells where splits is number of times to split width
var cells = nodes.size();
var splits = Math.sqrt(cells * bb.h / bb.w);
var rows = Math.round(splits);
var cols = Math.round(bb.w / bb.h * splits);
var small = function small(val) {
if (val == null) {
return Math.min(rows, cols);
} else {
var min = Math.min(rows, cols);
if (min == rows) {
rows = val;
} else {
cols = val;
}
}
};
var large = function large(val) {
if (val == null) {
return Math.max(rows, cols);
} else {
var max = Math.max(rows, cols);
if (max == rows) {
rows = val;
} else {
cols = val;
}
}
};
var oRows = options.rows;
var oCols = options.cols != null ? options.cols : options.columns;
// if rows or columns were set in options, use those values
if (oRows != null && oCols != null) {
rows = oRows;
cols = oCols;
} else if (oRows != null && oCols == null) {
rows = oRows;
cols = Math.ceil(cells / rows);
} else if (oRows == null && oCols != null) {
cols = oCols;
rows = Math.ceil(cells / cols);
}
// otherwise use the automatic values and adjust accordingly
// if rounding was up, see if we can reduce rows or columns
else if (cols * rows > cells) {
var sm = small();
var lg = large();
// reducing the small side takes away the most cells, so try it first
if ((sm - 1) * lg >= cells) {
small(sm - 1);
} else if ((lg - 1) * sm >= cells) {
large(lg - 1);
}
} else {
// if rounding was too low, add rows or columns
while (cols * rows < cells) {
var _sm = small();
var _lg = large();
// try to add to larger side first (adds less in multiplication)
if ((_lg + 1) * _sm >= cells) {
large(_lg + 1);
} else {
small(_sm + 1);
}
}
}
var cellWidth = bb.w / cols;
var cellHeight = bb.h / rows;
if (options.condense) {
cellWidth = 0;
cellHeight = 0;
}
if (options.avoidOverlap) {
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
var pos = node._private.position;
if (pos.x == null || pos.y == null) {
// for bb
pos.x = 0;
pos.y = 0;
}
var nbb = node.layoutDimensions(options);
var p = options.avoidOverlapPadding;
var w = nbb.w + p;
var h = nbb.h + p;
cellWidth = Math.max(cellWidth, w);
cellHeight = Math.max(cellHeight, h);
}
}
var cellUsed = {}; // e.g. 'c-0-2' => true
var used = function used(row, col) {
return cellUsed['c-' + row + '-' + col] ? true : false;
};
var use = function use(row, col) {
cellUsed['c-' + row + '-' + col] = true;
};
// to keep track of current cell position
var row = 0;
var col = 0;
var moveToNextCell = function moveToNextCell() {
col++;
if (col >= cols) {
col = 0;
row++;
}
};
// get a cache of all the manual positions
var id2manPos = {};
for (var _i = 0; _i < nodes.length; _i++) {
var _node = nodes[_i];
var rcPos = options.position(_node);
if (rcPos && (rcPos.row !== undefined || rcPos.col !== undefined)) {
// must have at least row or col def'd
var _pos = {
row: rcPos.row,
col: rcPos.col
};
if (_pos.col === undefined) {
// find unused col
_pos.col = 0;
while (used(_pos.row, _pos.col)) {
_pos.col++;
}
} else if (_pos.row === undefined) {
// find unused row
_pos.row = 0;
while (used(_pos.row, _pos.col)) {
_pos.row++;
}
}
id2manPos[_node.id()] = _pos;
use(_pos.row, _pos.col);
}
}
var getPos = function getPos(element, i) {
var x = void 0,
y = void 0;
if (element.locked() || element.isParent()) {
return false;
}
// see if we have a manual position set
var rcPos = id2manPos[element.id()];
if (rcPos) {
x = rcPos.col * cellWidth + cellWidth / 2 + bb.x1;
y = rcPos.row * cellHeight + cellHeight / 2 + bb.y1;
} else {
// otherwise set automatically
while (used(row, col)) {
moveToNextCell();
}
x = col * cellWidth + cellWidth / 2 + bb.x1;
y = row * cellHeight + cellHeight / 2 + bb.y1;
use(row, col);
moveToNextCell();
}
return { x: x, y: y };
};
nodes.layoutPositions(this, options, getPos);
}
return this; // chaining
};
module.exports = GridLayout;
/***/ }),
/* 103 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
// default layout options
var defaults = {
ready: function ready() {}, // on layoutready
stop: function stop() {} // on layoutstop
};
// constructor
// options : object containing layout options
function NullLayout(options) {
this.options = util.extend({}, defaults, options);
}
// runs the layout
NullLayout.prototype.run = function () {
var options = this.options;
var eles = options.eles; // elements to consider in the layout
var layout = this;
// cy is automatically populated for us in the constructor
var cy = options.cy; // jshint ignore:line
layout.emit('layoutstart');
// puts all nodes at (0, 0)
eles.nodes().positions(function () {
return {
x: 0,
y: 0
};
});
// trigger layoutready when each node has had its position set at least once
layout.one('layoutready', options.ready);
layout.emit('layoutready');
// trigger layoutstop when the layout stops (e.g. finishes)
layout.one('layoutstop', options.stop);
layout.emit('layoutstop');
return this; // chaining
};
// called on continuous layouts to stop them before they finish
NullLayout.prototype.stop = function () {
return this; // chaining
};
module.exports = NullLayout;
/***/ }),
/* 104 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var defaults = {
positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }
zoom: undefined, // the zoom level to set (prob want fit = false if set)
pan: undefined, // the pan level to set (prob want fit = false if set)
fit: true, // whether to fit to viewport
padding: 30, // padding on fit
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function PresetLayout(options) {
this.options = util.extend({}, defaults, options);
}
PresetLayout.prototype.run = function () {
var options = this.options;
var eles = options.eles;
var nodes = eles.nodes();
var posIsFn = is.fn(options.positions);
function getPosition(node) {
if (options.positions == null) {
return null;
}
if (posIsFn) {
return options.positions(node);
}
var pos = options.positions[node._private.data.id];
if (pos == null) {
return null;
}
return pos;
}
nodes.layoutPositions(this, options, function (node, i) {
var position = getPosition(node);
if (node.locked() || position == null) {
return false;
}
return position;
});
return this; // chaining
};
module.exports = PresetLayout;
/***/ }),
/* 105 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var defaults = {
fit: true, // whether to fit to viewport
padding: 30, // fit padding
boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function animateFilter(node, i) {
return true;
}, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: undefined, // callback on layoutready
stop: undefined, // callback on layoutstop
transform: function transform(node, position) {
return position;
} // transform a given node position. Useful for changing flow direction in discrete layouts
};
function RandomLayout(options) {
this.options = util.extend({}, defaults, options);
}
RandomLayout.prototype.run = function () {
var options = this.options;
var cy = options.cy;
var eles = options.eles;
var nodes = eles.nodes().not(':parent');
var bb = math.makeBoundingBox(options.boundingBox ? options.boundingBox : {
x1: 0, y1: 0, w: cy.width(), h: cy.height()
});
var getPos = function getPos(node, i) {
return {
x: bb.x1 + Math.round(Math.random() * bb.w),
y: bb.y1 + Math.round(Math.random() * bb.h)
};
};
nodes.layoutPositions(this, options, getPos);
return this; // chaining
};
module.exports = RandomLayout;
/***/ }),
/* 106 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = [{ name: 'null', impl: __webpack_require__(107) }, { name: 'base', impl: __webpack_require__(108) }, { name: 'canvas', impl: __webpack_require__(124) }];
/***/ }),
/* 107 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function NullRenderer(options) {
this.options = options;
this.notifications = 0; // for testing
}
var noop = function noop() {};
NullRenderer.prototype = {
recalculateRenderedStyle: noop,
notify: function notify() {
this.notifications++;
},
init: noop
};
module.exports = NullRenderer;
/***/ }),
/* 108 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var window = __webpack_require__(3);
var BaseRenderer = function BaseRenderer(options) {
this.init(options);
};
var BR = BaseRenderer;
var BRp = BR.prototype;
BRp.clientFunctions = ['redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl'];
BRp.init = function (options) {
var r = this;
r.options = options;
r.cy = options.cy;
var ctr = r.container = options.cy.container();
// prepend a stylesheet in the head such that
if (window) {
var document = window.document;
var head = document.head;
var stylesheetId = '__________cytoscape_stylesheet';
var className = '__________cytoscape_container';
var stylesheetAlreadyExists = document.getElementById(stylesheetId) != null;
if (ctr.className.indexOf(className) < 0) {
ctr.className = (ctr.className || '') + ' ' + className;
}
if (!stylesheetAlreadyExists) {
var stylesheet = document.createElement('style');
stylesheet.id = stylesheetId;
stylesheet.innerHTML = '.' + className + ' { position: relative; }';
head.insertBefore(stylesheet, head.children[0]); // first so lowest priority
}
var computedStyle = window.getComputedStyle(ctr);
var position = computedStyle.getPropertyValue('position');
if (position === 'static') {
util.error('A Cytoscape container has style position:static and so can not use UI extensions properly');
}
}
r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag
r.bezierProjPcts = [0.05, 0.225, 0.4, 0.5, 0.6, 0.775, 0.95];
//--Pointer-related data
r.hoverData = { down: null, last: null,
downTime: null, triggerMode: null,
dragging: false,
initialPan: [null, null], capture: false };
r.dragData = { possibleDragElements: [] };
r.touchData = {
start: null, capture: false,
// These 3 fields related to tap, taphold events
startPosition: [null, null, null, null, null, null],
singleTouchStartTime: null,
singleTouchMoved: true,
now: [null, null, null, null, null, null],
earlier: [null, null, null, null, null, null]
};
r.redraws = 0;
r.showFps = options.showFps;
r.debug = options.debug;
r.hideEdgesOnViewport = options.hideEdgesOnViewport;
r.hideLabelsOnViewport = options.hideLabelsOnViewport;
r.textureOnViewport = options.textureOnViewport;
r.wheelSensitivity = options.wheelSensitivity;
r.motionBlurEnabled = options.motionBlur; // on by default
r.forcedPixelRatio = options.pixelRatio;
r.motionBlur = options.motionBlur; // for initial kick off
r.motionBlurOpacity = options.motionBlurOpacity;
r.motionBlurTransparency = 1 - r.motionBlurOpacity;
r.motionBlurPxRatio = 1;
r.mbPxRBlurry = 1; //0.8;
r.minMbLowQualFrames = 4;
r.fullQualityMb = false;
r.clearedForMotionBlur = [];
r.desktopTapThreshold = options.desktopTapThreshold;
r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;
r.touchTapThreshold = options.touchTapThreshold;
r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;
r.tapholdDuration = 500;
r.bindings = [];
r.beforeRenderCallbacks = [];
r.beforeRenderPriorities = { // higher priority execs before lower one
animations: 400,
eleCalcs: 300,
eleTxrDeq: 200,
lyrTxrDeq: 100
};
r.registerNodeShapes();
r.registerArrowShapes();
r.registerCalculationListeners();
};
BRp.notify = function (params) {
var types;
var r = this;
// the renderer can't be notified after it's destroyed
if (this.destroyed) {
return;
}
if (is.array(params.type)) {
types = params.type;
} else {
types = [params.type];
}
var has = {};
for (var i = 0; i < types.length; i++) {
var type = types[i];
has[type] = true;
} // for
if (has['init']) {
r.load();
return;
}
if (has['destroy']) {
r.destroy();
return;
}
if (has['add'] || has['remove'] || has['load'] || has['zorder']) {
r.invalidateCachedZSortedEles();
}
if (has['viewport']) {
r.redrawHint('select', true);
}
if (has['load'] || has['resize']) {
r.invalidateContainerClientCoordsCache();
r.matchCanvasSize(r.container);
}
r.redrawHint('eles', true);
r.redrawHint('drag', true);
this.startRenderLoop();
this.redraw();
};
BRp.destroy = function () {
var r = this;
r.destroyed = true;
r.cy.stopAnimationLoop();
for (var i = 0; i < r.bindings.length; i++) {
var binding = r.bindings[i];
var b = binding;
var tgt = b.target;
(tgt.off || tgt.removeEventListener).apply(tgt, b.args);
}
r.bindings = [];
r.beforeRenderCallbacks = [];
r.onUpdateEleCalcsFns = [];
if (r.removeObserver) {
r.removeObserver.disconnect();
}
if (r.styleObserver) {
r.styleObserver.disconnect();
}
if (r.labelCalcDiv) {
try {
document.body.removeChild(r.labelCalcDiv); // eslint-disable-line no-undef
} catch (e) {
// ie10 issue #1014
}
}
};
[__webpack_require__(109), __webpack_require__(110), __webpack_require__(120), __webpack_require__(121), __webpack_require__(122), __webpack_require__(123)].forEach(function (props) {
util.extend(BRp, props);
});
module.exports = BR;
/***/ }),
/* 109 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var BRp = {};
BRp.arrowShapeWidth = 0.3;
BRp.registerArrowShapes = function () {
var arrowShapes = this.arrowShapes = {};
var renderer = this;
// Contract for arrow shapes:
// 0, 0 is arrow tip
// (0, 1) is direction towards node
// (1, 0) is right
//
// functional api:
// collide: check x, y in shape
// roughCollide: called before collide, no false negatives
// draw: draw
// spacing: dist(arrowTip, nodeBoundary)
// gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip
var bbCollide = function bbCollide(x, y, size, angle, translation, edgeWidth, padding) {
var x1 = translation.x - size / 2 - padding;
var x2 = translation.x + size / 2 + padding;
var y1 = translation.y - size / 2 - padding;
var y2 = translation.y + size / 2 + padding;
var inside = x1 <= x && x <= x2 && y1 <= y && y <= y2;
return inside;
};
var transform = function transform(x, y, size, angle, translation) {
var xRotated = x * Math.cos(angle) - y * Math.sin(angle);
var yRotated = x * Math.sin(angle) + y * Math.cos(angle);
var xScaled = xRotated * size;
var yScaled = yRotated * size;
var xTranslated = xScaled + translation.x;
var yTranslated = yScaled + translation.y;
return {
x: xTranslated,
y: yTranslated
};
};
var transformPoints = function transformPoints(pts, size, angle, translation) {
var retPts = [];
for (var i = 0; i < pts.length; i += 2) {
var x = pts[i];
var y = pts[i + 1];
retPts.push(transform(x, y, size, angle, translation));
}
return retPts;
};
var pointsToArr = function pointsToArr(pts) {
var ret = [];
for (var i = 0; i < pts.length; i++) {
var p = pts[i];
ret.push(p.x, p.y);
}
return ret;
};
var standardGap = function standardGap(edge) {
return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').pfValue * 2;
};
var defineArrowShape = function defineArrowShape(name, defn) {
if (is.string(defn)) {
defn = arrowShapes[defn];
}
arrowShapes[name] = util.extend({
name: name,
points: [-0.15, -0.3, 0.15, -0.3, 0.15, 0.3, -0.15, 0.3],
collide: function collide(x, y, size, angle, translation, padding) {
var points = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));
var inside = math.pointInsidePolygonPoints(x, y, points);
return inside;
},
roughCollide: bbCollide,
draw: function draw(context, size, angle, translation) {
var points = transformPoints(this.points, size, angle, translation);
renderer.arrowShapeImpl('polygon')(context, points);
},
spacing: function spacing(edge) {
return 0;
},
gap: standardGap
}, defn);
};
defineArrowShape('none', {
collide: util.falsify,
roughCollide: util.falsify,
draw: util.noop,
spacing: util.zeroify,
gap: util.zeroify
});
defineArrowShape('triangle', {
points: [-0.15, -0.3, 0, 0, 0.15, -0.3]
});
defineArrowShape('arrow', 'triangle');
defineArrowShape('triangle-backcurve', {
points: arrowShapes['triangle'].points,
controlPoint: [0, -0.15],
roughCollide: bbCollide,
draw: function draw(context, size, angle, translation, edgeWidth) {
var ptsTrans = transformPoints(this.points, size, angle, translation);
var ctrlPt = this.controlPoint;
var ctrlPtTrans = transform(ctrlPt[0], ctrlPt[1], size, angle, translation);
renderer.arrowShapeImpl(this.name)(context, ptsTrans, ctrlPtTrans);
},
gap: function gap(edge) {
return standardGap(edge) * 0.8;
}
});
defineArrowShape('triangle-tee', {
points: [-0.15, -0.3, 0, 0, 0.15, -0.3, -0.15, -0.3],
pointsTee: [-0.15, -0.4, -0.15, -0.5, 0.15, -0.5, 0.15, -0.4],
collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {
var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));
var teePts = pointsToArr(transformPoints(this.pointsTee, size + 2 * padding, angle, translation));
var inside = math.pointInsidePolygonPoints(x, y, triPts) || math.pointInsidePolygonPoints(x, y, teePts);
return inside;
},
draw: function draw(context, size, angle, translation, edgeWidth) {
var triPts = transformPoints(this.points, size, angle, translation);
var teePts = transformPoints(this.pointsTee, size, angle, translation);
renderer.arrowShapeImpl(this.name)(context, triPts, teePts);
}
});
defineArrowShape('triangle-cross', {
points: [-0.15, -0.3, 0, 0, 0.15, -0.3, -0.15, -0.3],
baseCrossLinePts: [-0.15, -0.4, // first half of the rectangle
-0.15, -0.4, 0.15, -0.4, // second half of the rectangle
0.15, -0.4],
crossLinePts: function crossLinePts(size, edgeWidth) {
// shift points so that the distance between the cross points matches edge width
var p = this.baseCrossLinePts.slice();
var shiftFactor = edgeWidth / size;
var y0 = 3;
var y1 = 5;
p[y0] = p[y0] - shiftFactor;
p[y1] = p[y1] - shiftFactor;
return p;
},
collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {
var triPts = pointsToArr(transformPoints(this.points, size + 2 * padding, angle, translation));
var teePts = pointsToArr(transformPoints(this.crossLinePts(size, edgeWidth), size + 2 * padding, angle, translation));
var inside = math.pointInsidePolygonPoints(x, y, triPts) || math.pointInsidePolygonPoints(x, y, teePts);
return inside;
},
draw: function draw(context, size, angle, translation, edgeWidth) {
var triPts = transformPoints(this.points, size, angle, translation);
var crossLinePts = transformPoints(this.crossLinePts(size, edgeWidth), size, angle, translation);
renderer.arrowShapeImpl(this.name)(context, triPts, crossLinePts);
}
});
defineArrowShape('vee', {
points: [-0.15, -0.3, 0, 0, 0.15, -0.3, 0, -0.15],
gap: function gap(edge) {
return standardGap(edge) * 0.525;
}
});
defineArrowShape('circle', {
radius: 0.15,
collide: function collide(x, y, size, angle, translation, edgeWidth, padding) {
var t = translation;
var inside = Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2 * padding) * this.radius, 2);
return inside;
},
draw: function draw(context, size, angle, translation, edgeWidth) {
renderer.arrowShapeImpl(this.name)(context, translation.x, translation.y, this.radius * size);
},
spacing: function spacing(edge) {
return renderer.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.radius;
}
});
defineArrowShape('tee', {
points: [-0.15, 0, -0.15, -0.1, 0.15, -0.1, 0.15, 0],
spacing: function spacing(edge) {
return 1;
},
gap: function gap(edge) {
return 1;
}
});
defineArrowShape('square', {
points: [-0.15, 0.00, 0.15, 0.00, 0.15, -0.3, -0.15, -0.3]
});
defineArrowShape('diamond', {
points: [-0.15, -0.15, 0, -0.3, 0.15, -0.15, 0, 0],
gap: function gap(edge) {
return edge.pstyle('width').pfValue * edge.pstyle('arrow-scale').value;
}
});
};
module.exports = BRp;
/***/ }),
/* 110 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var BRp = {};
[__webpack_require__(111), __webpack_require__(112), __webpack_require__(113), __webpack_require__(114), __webpack_require__(115), __webpack_require__(116), __webpack_require__(117), __webpack_require__(118), __webpack_require__(119)].forEach(function (props) {
util.extend(BRp, props);
});
module.exports = BRp;
/***/ }),
/* 111 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var window = __webpack_require__(3);
var math = __webpack_require__(2);
var util = __webpack_require__(1);
var window = __webpack_require__(3);
var BRp = {};
// Project mouse
BRp.projectIntoViewport = function (clientX, clientY) {
var cy = this.cy;
var offsets = this.findContainerClientCoords();
var offsetLeft = offsets[0];
var offsetTop = offsets[1];
var scale = offsets[4];
var pan = cy.pan();
var zoom = cy.zoom();
var x = ((clientX - offsetLeft) / scale - pan.x) / zoom;
var y = ((clientY - offsetTop) / scale - pan.y) / zoom;
return [x, y];
};
BRp.findContainerClientCoords = function () {
if (this.containerBB) {
return this.containerBB;
}
var container = this.container;
var rect = container.getBoundingClientRect();
var style = window.getComputedStyle(container);
var styleValue = function styleValue(name) {
return parseFloat(style.getPropertyValue(name));
};
var padding = {
left: styleValue('padding-left'),
right: styleValue('padding-right'),
top: styleValue('padding-top'),
bottom: styleValue('padding-bottom')
};
var border = {
left: styleValue('border-left-width'),
right: styleValue('border-right-width'),
top: styleValue('border-top-width'),
bottom: styleValue('border-bottom-width')
};
var clientWidth = container.clientWidth;
var clientHeight = container.clientHeight;
var paddingHor = padding.left + padding.right;
var paddingVer = padding.top + padding.bottom;
var borderHor = border.left + border.right;
var borderVer = border.top + border.bottom;
var scale = rect.width / (clientWidth + borderHor);
var unscaledW = clientWidth - paddingHor;
var unscaledH = clientHeight - paddingVer;
var scaledW = rect.width - (paddingHor + borderHor) * scale;
var scaledH = rect.height - (paddingVer + borderVer) * scale;
var left = rect.left + padding.left + border.left;
var top = rect.top + padding.top + border.top;
return this.containerBB = [left, top, unscaledW, unscaledH, scale];
};
BRp.invalidateContainerClientCoordsCache = function () {
this.containerBB = null;
};
BRp.findNearestElement = function (x, y, interactiveElementsOnly, isTouch) {
return this.findNearestElements(x, y, interactiveElementsOnly, isTouch)[0];
};
BRp.findNearestElements = function (x, y, interactiveElementsOnly, isTouch) {
var self = this;
var r = this;
var eles = r.getCachedZSortedEles();
var near = []; // 1 node max, 1 edge max
var zoom = r.cy.zoom();
var hasCompounds = r.cy.hasCompoundNodes();
var edgeThreshold = (isTouch ? 24 : 8) / zoom;
var nodeThreshold = (isTouch ? 8 : 2) / zoom;
var labelThreshold = (isTouch ? 8 : 2) / zoom;
var minSqDist = Infinity;
var nearEdge;
var nearNode;
if (interactiveElementsOnly) {
eles = eles.interactive;
}
function addEle(ele, sqDist) {
if (ele.isNode()) {
if (nearNode) {
return; // can't replace node
} else {
nearNode = ele;
near.push(ele);
}
}
if (ele.isEdge() && (sqDist == null || sqDist < minSqDist)) {
if (nearEdge) {
// then replace existing edge
// can replace only if same z-index
if (nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value && nearEdge.pstyle('z-compound-depth').value === ele.pstyle('z-compound-depth').value) {
for (var i = 0; i < near.length; i++) {
if (near[i].isEdge()) {
near[i] = ele;
nearEdge = ele;
minSqDist = sqDist != null ? sqDist : minSqDist;
break;
}
}
}
} else {
near.push(ele);
nearEdge = ele;
minSqDist = sqDist != null ? sqDist : minSqDist;
}
}
}
function checkNode(node) {
var width = node.outerWidth() + 2 * nodeThreshold;
var height = node.outerHeight() + 2 * nodeThreshold;
var hw = width / 2;
var hh = height / 2;
var pos = node.position();
if (pos.x - hw <= x && x <= pos.x + hw // bb check x
&& pos.y - hh <= y && y <= pos.y + hh // bb check y
) {
var shape = r.nodeShapes[self.getNodeShape(node)];
if (shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)) {
addEle(node, 0);
return true;
}
}
}
function checkEdge(edge) {
var _p = edge._private;
var rs = _p.rscratch;
var styleWidth = edge.pstyle('width').pfValue;
var scale = edge.pstyle('arrow-scale').value;
var width = styleWidth / 2 + edgeThreshold; // more like a distance radius from centre
var widthSq = width * width;
var width2 = width * 2;
var src = _p.source;
var tgt = _p.target;
var inEdgeBB = false;
var sqDist;
if (rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack') {
var pts = rs.allpts;
for (var i = 0; i + 3 < pts.length; i += 2) {
if ((inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], width2)) && widthSq > (sqDist = math.sqdistToFiniteLine(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3]))) {
addEle(edge, sqDist);
return true;
}
}
} else if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') {
var pts = rs.allpts;
for (var i = 0; i + 5 < rs.allpts.length; i += 4) {
if ((inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5], width2)) && widthSq > (sqDist = math.sqdistToQuadraticBezier(x, y, pts[i], pts[i + 1], pts[i + 2], pts[i + 3], pts[i + 4], pts[i + 5]))) {
addEle(edge, sqDist);
return true;
}
}
}
// if we're close to the edge but didn't hit it, maybe we hit its arrows
var src = src || _p.source;
var tgt = tgt || _p.target;
var arSize = self.getArrowWidth(styleWidth, scale);
var arrows = [{ name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle }, { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle }, { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle }, { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }];
for (var i = 0; i < arrows.length; i++) {
var ar = arrows[i];
var shape = r.arrowShapes[edge.pstyle(ar.name + '-arrow-shape').value];
var edgeWidth = edge.pstyle('width').pfValue;
if (shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeWidth, edgeThreshold) && shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeWidth, edgeThreshold)) {
addEle(edge);
return true;
}
}
// for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)
if (hasCompounds && near.length > 0) {
checkNode(src);
checkNode(tgt);
}
}
function preprop(obj, name, pre) {
return util.getPrefixedProperty(obj, name, pre);
}
function checkLabel(ele, prefix) {
var _p = ele._private;
var th = labelThreshold;
var prefixDash;
if (prefix) {
prefixDash = prefix + '-';
} else {
prefixDash = '';
}
var text = ele.pstyle(prefixDash + 'label').value;
var eventsEnabled = ele.pstyle('text-events').strValue === 'yes';
if (!eventsEnabled || !text) {
return;
}
var rstyle = _p.rstyle;
var bw = ele.pstyle('text-border-width').pfValue;
var pw = ele.pstyle('text-background-padding').pfValue;
var lw = preprop(rstyle, 'labelWidth', prefix) + bw + 2 * th + 2 * pw;
var lh = preprop(rstyle, 'labelHeight', prefix) + bw + 2 * th + 2 * pw;
var lx = preprop(rstyle, 'labelX', prefix);
var ly = preprop(rstyle, 'labelY', prefix);
var theta = preprop(_p.rscratch, 'labelAngle', prefix);
var lx1 = lx - lw / 2;
var lx2 = lx + lw / 2;
var ly1 = ly - lh / 2;
var ly2 = ly + lh / 2;
if (theta) {
var cos = Math.cos(theta);
var sin = Math.sin(theta);
var rotate = function rotate(x, y) {
x = x - lx;
y = y - ly;
return {
x: x * cos - y * sin + lx,
y: x * sin + y * cos + ly
};
};
var px1y1 = rotate(lx1, ly1);
var px1y2 = rotate(lx1, ly2);
var px2y1 = rotate(lx2, ly1);
var px2y2 = rotate(lx2, ly2);
var points = [px1y1.x, px1y1.y, px2y1.x, px2y1.y, px2y2.x, px2y2.y, px1y2.x, px1y2.y];
if (math.pointInsidePolygonPoints(x, y, points)) {
addEle(ele);
return true;
}
} else {
// do a cheaper bb check
var bb = {
w: lw,
h: lh,
x1: lx1,
x2: lx2,
y1: ly1,
y2: ly2
};
if (math.inBoundingBox(bb, x, y)) {
addEle(ele);
return true;
}
}
}
for (var i = eles.length - 1; i >= 0; i--) {
// reverse order for precedence
var ele = eles[i];
if (ele.isNode()) {
checkNode(ele) || checkLabel(ele);
} else {
// then edge
checkEdge(ele) || checkLabel(ele) || checkLabel(ele, 'source') || checkLabel(ele, 'target');
}
}
return near;
};
// 'Give me everything from this box'
BRp.getAllInBox = function (x1, y1, x2, y2) {
var eles = this.getCachedZSortedEles().interactive;
var box = [];
var x1c = Math.min(x1, x2);
var x2c = Math.max(x1, x2);
var y1c = Math.min(y1, y2);
var y2c = Math.max(y1, y2);
x1 = x1c;
x2 = x2c;
y1 = y1c;
y2 = y2c;
var boxBb = math.makeBoundingBox({
x1: x1, y1: y1,
x2: x2, y2: y2
});
for (var e = 0; e < eles.length; e++) {
var ele = eles[e];
if (ele.isNode()) {
var node = ele;
var nodeBb = node.boundingBox({
includeNodes: true,
includeEdges: false,
includeLabels: false
});
if (math.boundingBoxesIntersect(boxBb, nodeBb) && !math.boundingBoxInBoundingBox(nodeBb, boxBb)) {
box.push(node);
}
} else {
var edge = ele;
var _p = edge._private;
var rs = _p.rscratch;
if (rs.startX != null && rs.startY != null && !math.inBoundingBox(boxBb, rs.startX, rs.startY)) {
continue;
}
if (rs.endX != null && rs.endY != null && !math.inBoundingBox(boxBb, rs.endX, rs.endY)) {
continue;
}
if (rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack') {
var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;
var allInside = true;
for (var i = 0; i < pts.length; i++) {
if (!math.pointInBoundingBox(boxBb, pts[i])) {
allInside = false;
break;
}
}
if (allInside) {
box.push(edge);
}
} else if (rs.edgeType === 'haystack' || rs.edgeType === 'straight') {
box.push(edge);
}
}
}
return box;
};
module.exports = BRp;
/***/ }),
/* 112 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var BRp = {};
BRp.calculateArrowAngles = function (edge) {
var rs = edge._private.rscratch;
var isHaystack = rs.edgeType === 'haystack';
var isBezier = rs.edgeType === 'bezier';
var isMultibezier = rs.edgeType === 'multibezier';
var isSegments = rs.edgeType === 'segments';
var isCompound = rs.edgeType === 'compound';
var isSelf = rs.edgeType === 'self';
// Displacement gives direction for arrowhead orientation
var dispX, dispY;
var startX, startY, endX, endY, midX, midY;
if (isHaystack) {
startX = rs.haystackPts[0];
startY = rs.haystackPts[1];
endX = rs.haystackPts[2];
endY = rs.haystackPts[3];
} else {
startX = rs.arrowStartX;
startY = rs.arrowStartY;
endX = rs.arrowEndX;
endY = rs.arrowEndY;
}
midX = rs.midX;
midY = rs.midY;
// source
//
if (isSegments) {
dispX = startX - rs.segpts[0];
dispY = startY - rs.segpts[1];
} else if (isMultibezier || isCompound || isSelf || isBezier) {
var pts = rs.allpts;
var bX = math.qbezierAt(pts[0], pts[2], pts[4], 0.1);
var bY = math.qbezierAt(pts[1], pts[3], pts[5], 0.1);
dispX = startX - bX;
dispY = startY - bY;
} else {
dispX = startX - midX;
dispY = startY - midY;
}
rs.srcArrowAngle = math.getAngleFromDisp(dispX, dispY);
// mid target
//
var midX = rs.midX;
var midY = rs.midY;
if (isHaystack) {
midX = (startX + endX) / 2;
midY = (startY + endY) / 2;
}
dispX = endX - startX;
dispY = endY - startY;
if (isSegments) {
var pts = rs.allpts;
if (pts.length / 2 % 2 === 0) {
var i2 = pts.length / 2;
var i1 = i2 - 2;
dispX = pts[i2] - pts[i1];
dispY = pts[i2 + 1] - pts[i1 + 1];
} else {
var i2 = pts.length / 2 - 1;
var i1 = i2 - 2;
var i3 = i2 + 2;
dispX = pts[i2] - pts[i1];
dispY = pts[i2 + 1] - pts[i1 + 1];
}
} else if (isMultibezier || isCompound || isSelf) {
var pts = rs.allpts;
var cpts = rs.ctrlpts;
var bp0x, bp0y;
var bp1x, bp1y;
if (cpts.length / 2 % 2 === 0) {
var p0 = pts.length / 2 - 1; // startpt
var ic = p0 + 2;
var p1 = ic + 2;
bp0x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.0);
bp0y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0);
bp1x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.0001);
bp1y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.0001);
} else {
var ic = pts.length / 2 - 1; // ctrpt
var p0 = ic - 2; // startpt
var p1 = ic + 2; // endpt
bp0x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.4999);
bp0y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.4999);
bp1x = math.qbezierAt(pts[p0], pts[ic], pts[p1], 0.5);
bp1y = math.qbezierAt(pts[p0 + 1], pts[ic + 1], pts[p1 + 1], 0.5);
}
dispX = bp1x - bp0x;
dispY = bp1y - bp0y;
}
rs.midtgtArrowAngle = math.getAngleFromDisp(dispX, dispY);
rs.midDispX = dispX;
rs.midDispY = dispY;
// mid source
//
dispX *= -1;
dispY *= -1;
if (isSegments) {
var pts = rs.allpts;
if (pts.length / 2 % 2 === 0) {
// already ok
} else {
var i2 = pts.length / 2 - 1;
var i3 = i2 + 2;
dispX = -(pts[i3] - pts[i2]);
dispY = -(pts[i3 + 1] - pts[i2 + 1]);
}
}
rs.midsrcArrowAngle = math.getAngleFromDisp(dispX, dispY);
// target
//
if (isSegments) {
dispX = endX - rs.segpts[rs.segpts.length - 2];
dispY = endY - rs.segpts[rs.segpts.length - 1];
} else if (isMultibezier || isCompound || isSelf || isBezier) {
var pts = rs.allpts;
var l = pts.length;
var bX = math.qbezierAt(pts[l - 6], pts[l - 4], pts[l - 2], 0.9);
var bY = math.qbezierAt(pts[l - 5], pts[l - 3], pts[l - 1], 0.9);
dispX = endX - bX;
dispY = endY - bY;
} else {
dispX = endX - midX;
dispY = endY - midY;
}
rs.tgtArrowAngle = math.getAngleFromDisp(dispX, dispY);
};
BRp.getArrowWidth = BRp.getArrowHeight = function (edgeWidth, scale) {
var cache = this.arrowWidthCache = this.arrowWidthCache || {};
var cachedVal = cache[edgeWidth + ', ' + scale];
if (cachedVal) {
return cachedVal;
}
cachedVal = Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29) * scale;
cache[edgeWidth + ', ' + scale] = cachedVal;
return cachedVal;
};
module.exports = BRp;
/***/ }),
/* 113 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var BRp = {};
BRp.findEdgeControlPoints = function (edges) {
if (!edges || edges.length === 0) {
return;
}
var r = this;
var cy = r.cy;
var hasCompounds = cy.hasCompoundNodes();
var hashTable = {};
var pairIds = [];
var haystackEdges = [];
// create a table of edge (src, tgt) => list of edges between them
var pairId;
for (var i = 0; i < edges.length; i++) {
var edge = edges[i];
var _p = edge._private;
var data = _p.data;
var curveStyle = edge.pstyle('curve-style').value;
var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';
var edgeIsBezier = curveStyle === 'unbundled-bezier' || curveStyle === 'bezier';
// ignore edges who are not to be displayed
// they shouldn't take up space
if (edge.pstyle('display').value === 'none') {
continue;
}
if (curveStyle === 'haystack') {
haystackEdges.push(edge);
continue;
}
var srcId = data.source;
var tgtId = data.target;
pairId = srcId > tgtId ? tgtId + '$-$' + srcId : srcId + '$-$' + tgtId;
if (edgeIsUnbundled) {
pairId = 'unbundled' + '$-$' + data.id;
}
var tableEntry = hashTable[pairId];
if (tableEntry == null) {
tableEntry = hashTable[pairId] = [];
pairIds.push(pairId);
}
tableEntry.push(edge);
if (edgeIsUnbundled) {
tableEntry.hasUnbundled = true;
}
if (edgeIsBezier) {
tableEntry.hasBezier = true;
}
}
var src, tgt, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape;
var vectorNormInverse;
var badBezier;
// for each pair (src, tgt), create the ctrl pts
// Nested for loop is OK; total number of iterations for both loops = edgeCount
for (var p = 0; p < pairIds.length; p++) {
pairId = pairIds[p];
var pairEdges = hashTable[pairId];
// for each pair id, the edges should be sorted by index
pairEdges.sort(function (edge1, edge2) {
return edge1.poolIndex() - edge2.poolIndex();
});
src = pairEdges[0]._private.source;
tgt = pairEdges[0]._private.target;
// make sure src/tgt distinction is consistent for bundled edges
if (!pairEdges.hasUnbundled && src.id() > tgt.id()) {
var temp = src;
src = tgt;
tgt = temp;
}
srcPos = src.position();
tgtPos = tgt.position();
srcW = src.outerWidth();
srcH = src.outerHeight();
tgtW = tgt.outerWidth();
tgtH = tgt.outerHeight();
srcShape = r.nodeShapes[this.getNodeShape(src)];
tgtShape = r.nodeShapes[this.getNodeShape(tgt)];
badBezier = false;
var edge;
var edge_p;
var rs;
var dirCounts = {
'north': 0,
'west': 0,
'south': 0,
'east': 0,
'northwest': 0,
'southwest': 0,
'northeast': 0,
'southeast': 0
};
var srcX2 = srcPos.x;
var srcY2 = srcPos.y;
var srcW2 = srcW;
var srcH2 = srcH;
var tgtX2 = tgtPos.x;
var tgtY2 = tgtPos.y;
var tgtW2 = tgtW;
var tgtH2 = tgtH;
var numEdges2 = pairEdges.length;
for (var i = 0; i < pairEdges.length; i++) {
edge = pairEdges[i];
edge_p = edge._private;
rs = edge_p.rscratch;
var edgeIndex1 = rs.lastEdgeIndex;
var edgeIndex2 = i;
var numEdges1 = rs.lastNumEdges;
var curveStyle = edge.pstyle('curve-style').value;
var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';
// whether the normalised pair order is the reverse of the edge's src-tgt order
var edgeIsSwapped = src.id() !== edge.source().id();
var ctrlptDists = edge.pstyle('control-point-distances');
var loopDir = edge.pstyle('loop-direction').pfValue;
var loopSwp = edge.pstyle('loop-sweep').pfValue;
var ctrlptWs = edge.pstyle('control-point-weights');
var bezierN = ctrlptDists && ctrlptWs ? Math.min(ctrlptDists.value.length, ctrlptWs.value.length) : 1;
var stepSize = edge.pstyle('control-point-step-size').pfValue;
var ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[0] : undefined;
var ctrlptWeight = ctrlptWs.value[0];
var edgeDistances = edge.pstyle('edge-distances').value;
var srcDistFNode = edge.pstyle('source-distance-from-node').pfValue;
var tgtDistFNode = edge.pstyle('target-distance-from-node').pfValue;
var segmentWs = edge.pstyle('segment-weights');
var segmentDs = edge.pstyle('segment-distances');
var segmentsN = Math.min(segmentWs.pfValue.length, segmentDs.pfValue.length);
var srcEndpt = edge.pstyle('source-endpoint').value;
var tgtEndpt = edge.pstyle('target-endpoint').value;
var srcArrShape = edge.pstyle('source-arrow-shape').value;
var tgtArrShape = edge.pstyle('target-arrow-shape').value;
var arrowScale = edge.pstyle('arrow-scale').value;
var lineWidth = edge.pstyle('width').pfValue;
var srcX1 = rs.lastSrcCtlPtX;
var srcY1 = rs.lastSrcCtlPtY;
var srcW1 = rs.lastSrcCtlPtW;
var srcH1 = rs.lastSrcCtlPtH;
var tgtX1 = rs.lastTgtCtlPtX;
var tgtY1 = rs.lastTgtCtlPtY;
var tgtW1 = rs.lastTgtCtlPtW;
var tgtH1 = rs.lastTgtCtlPtH;
var curveStyle1 = rs.lastCurveStyle;
var curveStyle2 = curveStyle;
var ctrlptDists1 = rs.lastCtrlptDists;
var ctrlptDists2 = ctrlptDists ? ctrlptDists.strValue : null;
var ctrlptWs1 = rs.lastCtrlptWs;
var ctrlptWs2 = ctrlptWs.strValue;
var segmentWs1 = rs.lastSegmentWs;
var segmentWs2 = segmentWs.strValue;
var segmentDs1 = rs.lastSegmentDs;
var segmentDs2 = segmentDs.strValue;
var stepSize1 = rs.lastStepSize;
var stepSize2 = stepSize;
var loopDir1 = rs.lastLoopDir;
var loopDir2 = loopDir;
var loopSwp1 = rs.lastLoopSwp;
var loopSwp2 = loopSwp;
var edgeDistances1 = rs.lastEdgeDistances;
var edgeDistances2 = edgeDistances;
var srcDistFNode1 = rs.lastSrcDistFNode;
var srcDistFNode2 = srcDistFNode;
var tgtDistFNode1 = rs.lastTgtDistFNode;
var tgtDistFNode2 = tgtDistFNode;
var srcEndpt1 = rs.lastSrcEndpt;
var srcEndpt2 = srcEndpt;
var tgtEndpt1 = rs.lastTgtEndpt;
var tgtEndpt2 = tgtEndpt;
var srcArr1 = rs.lastSrcArr;
var srcArr2 = srcArrShape;
var tgtArr1 = rs.lastTgtArr;
var tgtArr2 = tgtArrShape;
var lineW1 = rs.lastLineW;
var lineW2 = lineWidth;
var arrScl1 = rs.lastArrScl;
var arrScl2 = arrowScale;
if (badBezier) {
rs.badBezier = true;
} else {
rs.badBezier = false;
}
var ptCacheHit;
if (srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2 && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2 && curveStyle1 === curveStyle2 && ctrlptDists1 === ctrlptDists2 && ctrlptWs1 === ctrlptWs2 && segmentWs1 === segmentWs2 && segmentDs1 === segmentDs2 && stepSize1 === stepSize2 && loopDir1 === loopDir2 && loopSwp1 === loopSwp2 && edgeDistances1 === edgeDistances2 && srcDistFNode1 === srcDistFNode2 && tgtDistFNode1 === tgtDistFNode2 && srcEndpt1 === srcEndpt2 && tgtEndpt1 === tgtEndpt2 && srcArr1 === srcArr2 && tgtArr1 === tgtArr2 && lineW1 === lineW2 && arrScl1 === arrScl2 && (edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2 || edgeIsUnbundled)) {
ptCacheHit = true; // then the control points haven't changed and we can skip calculating them
} else {
ptCacheHit = false;
rs.lastSrcCtlPtX = srcX2;
rs.lastSrcCtlPtY = srcY2;
rs.lastSrcCtlPtW = srcW2;
rs.lastSrcCtlPtH = srcH2;
rs.lastTgtCtlPtX = tgtX2;
rs.lastTgtCtlPtY = tgtY2;
rs.lastTgtCtlPtW = tgtW2;
rs.lastTgtCtlPtH = tgtH2;
rs.lastEdgeIndex = edgeIndex2;
rs.lastNumEdges = numEdges2;
rs.lastCurveStyle = curveStyle2;
rs.lastCtrlptDists = ctrlptDists2;
rs.lastCtrlptWs = ctrlptWs2;
rs.lastSegmentDs = segmentDs2;
rs.lastSegmentWs = segmentWs2;
rs.lastStepSize = stepSize2;
rs.lastLoopDir = loopDir2;
rs.lastLoopSwp = loopSwp2;
rs.lastEdgeDistances = edgeDistances2;
rs.lastSrcDistFNode = srcDistFNode2;
rs.lastTgtDistFNode = tgtDistFNode2;
rs.lastSrcEndpt = srcEndpt2;
rs.lastTgtEndpt = tgtEndpt2;
rs.lastSrcArr = srcArr2;
rs.lastTgtArr = tgtArr2;
rs.lastLineW = lineW2;
rs.lastArrScl = arrScl2;
}
if (!ptCacheHit) {
if (!pairEdges.calculatedIntersection && src !== tgt && (pairEdges.hasBezier || pairEdges.hasUnbundled)) {
pairEdges.calculatedIntersection = true;
// pt outside src shape to calc distance/displacement from src to tgt
var srcOutside = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, tgtPos.x, tgtPos.y, 0);
pairEdges.srcIntn = srcOutside;
// pt outside tgt shape to calc distance/displacement from src to tgt
var tgtOutside = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, srcPos.x, srcPos.y, 0);
pairEdges.tgtIntn = tgtOutside;
var midptSrcPts = {
x1: srcOutside[0],
x2: tgtOutside[0],
y1: srcOutside[1],
y2: tgtOutside[1]
};
var posPts = {
x1: srcPos.x,
x2: tgtPos.x,
y1: srcPos.y,
y2: tgtPos.y
};
var dy = tgtOutside[1] - srcOutside[1];
var dx = tgtOutside[0] - srcOutside[0];
var l = Math.sqrt(dx * dx + dy * dy);
var vector = {
x: dx,
y: dy
};
var vectorNorm = {
x: vector.x / l,
y: vector.y / l
};
vectorNormInverse = {
x: -vectorNorm.y,
y: vectorNorm.x
};
// if node shapes overlap, then no ctrl pts to draw
if (tgtShape.checkPoint(srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y) && srcShape.checkPoint(tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y)) {
vectorNormInverse = {};
badBezier = true;
}
}
if (!edgeIsSwapped) {
rs.srcIntn = pairEdges.srcIntn;
rs.tgtIntn = pairEdges.tgtIntn;
} else {
// ensure that the per-edge cached value for intersections are correct for swapped bundled edges
rs.srcIntn = pairEdges.tgtIntn;
rs.tgtIntn = pairEdges.srcIntn;
}
if (src === tgt) {
// Self-edge
rs.edgeType = 'self';
var j = i;
var loopDist = stepSize;
if (edgeIsUnbundled) {
j = 0;
loopDist = ctrlptDist;
}
var loopAngle = loopDir - Math.PI / 2;
var outAngle = loopAngle - loopSwp / 2;
var inAngle = loopAngle + loopSwp / 2;
// increase by step size for overlapping loops, keyed on direction and sweep values
var dc = String(loopDir + '_' + loopSwp);
j = dirCounts[dc] === undefined ? dirCounts[dc] = 0 : ++dirCounts[dc];
rs.ctrlpts = [srcPos.x + Math.cos(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(outAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.x + Math.cos(inAngle) * 1.4 * loopDist * (j / 3 + 1), srcPos.y + Math.sin(inAngle) * 1.4 * loopDist * (j / 3 + 1)];
} else if (hasCompounds && (src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild()) && (src.parents().anySame(tgt) || tgt.parents().anySame(src))) {
// Compound edge
rs.edgeType = 'compound';
// because the line approximation doesn't apply for compound beziers
// (loop/self edges are already elided b/c of cheap src==tgt check)
rs.badBezier = false;
var j = i;
var loopDist = stepSize;
if (edgeIsUnbundled) {
j = 0;
loopDist = ctrlptDist;
}
var loopW = 50;
var loopaPos = {
x: srcPos.x - srcW / 2,
y: srcPos.y - srcH / 2
};
var loopbPos = {
x: tgtPos.x - tgtW / 2,
y: tgtPos.y - tgtH / 2
};
var loopPos = {
x: Math.min(loopaPos.x, loopbPos.x),
y: Math.min(loopaPos.y, loopbPos.y)
};
// avoids cases with impossible beziers
var minCompoundStretch = 0.5;
var compoundStretchA = Math.max(minCompoundStretch, Math.log(srcW * 0.01));
var compoundStretchB = Math.max(minCompoundStretch, Math.log(tgtW * 0.01));
rs.ctrlpts = [loopPos.x, loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA, loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB, loopPos.y];
} else if (curveStyle === 'segments') {
// Segments (multiple straight lines)
rs.edgeType = 'segments';
rs.segpts = [];
for (var s = 0; s < segmentsN; s++) {
var w = segmentWs.pfValue[s];
var d = segmentDs.pfValue[s];
var w1 = 1 - w;
var w2 = w;
var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts;
var adjustedMidpt = {
x: midptPts.x1 * w1 + midptPts.x2 * w2,
y: midptPts.y1 * w1 + midptPts.y2 * w2
};
rs.segpts.push(adjustedMidpt.x + vectorNormInverse.x * d, adjustedMidpt.y + vectorNormInverse.y * d);
}
// Straight edge
} else if (pairEdges.length % 2 === 1 && i === Math.floor(pairEdges.length / 2) && !edgeIsUnbundled) {
rs.edgeType = 'straight';
} else {
// (Multi)bezier
var multi = edgeIsUnbundled;
rs.edgeType = multi ? 'multibezier' : 'bezier';
rs.ctrlpts = [];
for (var b = 0; b < bezierN; b++) {
var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize;
var manctrlptDist;
var sign = math.signum(normctrlptDist);
if (multi) {
ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size
ctrlptWeight = ctrlptWs.value[b];
}
if (edgeIsUnbundled) {
// multi or single unbundled
manctrlptDist = ctrlptDist;
} else {
manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;
}
var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;
var w1 = 1 - ctrlptWeight;
var w2 = ctrlptWeight;
if (edgeIsSwapped) {
var temp = w1;
w1 = w2;
w2 = temp;
}
var midptPts = edgeDistances === 'node-position' ? posPts : midptSrcPts;
var adjustedMidpt = {
x: midptPts.x1 * w1 + midptPts.x2 * w2,
y: midptPts.y1 * w1 + midptPts.y2 * w2
};
rs.ctrlpts.push(adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint, adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint);
}
}
// find endpts for edge
this.findEndpoints(edge);
var badStart = !is.number(rs.startX) || !is.number(rs.startY);
var badAStart = !is.number(rs.arrowStartX) || !is.number(rs.arrowStartY);
var badEnd = !is.number(rs.endX) || !is.number(rs.endY);
var badAEnd = !is.number(rs.arrowEndX) || !is.number(rs.arrowEndY);
var minCpADistFactor = 3;
var arrowW = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth;
var minCpADist = minCpADistFactor * arrowW;
if (rs.edgeType === 'bezier') {
var startACpDist = math.dist({ x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY });
var closeStartACp = startACpDist < minCpADist;
var endACpDist = math.dist({ x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY });
var closeEndACp = endACpDist < minCpADist;
var overlapping = false;
if (badStart || badAStart || closeStartACp) {
overlapping = true;
// project control point along line from src centre to outside the src shape
// (otherwise intersection will yield nothing)
var cpD = { // delta
x: rs.ctrlpts[0] - srcPos.x,
y: rs.ctrlpts[1] - srcPos.y
};
var cpL = Math.sqrt(cpD.x * cpD.x + cpD.y * cpD.y); // length of line
var cpM = { // normalised delta
x: cpD.x / cpL,
y: cpD.y / cpL
};
var radius = Math.max(srcW, srcH);
var cpProj = { // *2 radius guarantees outside shape
x: rs.ctrlpts[0] + cpM.x * 2 * radius,
y: rs.ctrlpts[1] + cpM.y * 2 * radius
};
var srcCtrlPtIntn = srcShape.intersectLine(srcPos.x, srcPos.y, srcW, srcH, cpProj.x, cpProj.y, 0);
if (closeStartACp) {
rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);
rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);
} else {
rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;
rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;
}
}
if (badEnd || badAEnd || closeEndACp) {
overlapping = true;
// project control point along line from tgt centre to outside the tgt shape
// (otherwise intersection will yield nothing)
var cpD = { // delta
x: rs.ctrlpts[0] - tgtPos.x,
y: rs.ctrlpts[1] - tgtPos.y
};
var cpL = Math.sqrt(cpD.x * cpD.x + cpD.y * cpD.y); // length of line
var cpM = { // normalised delta
x: cpD.x / cpL,
y: cpD.y / cpL
};
var radius = Math.max(srcW, srcH);
var cpProj = { // *2 radius guarantees outside shape
x: rs.ctrlpts[0] + cpM.x * 2 * radius,
y: rs.ctrlpts[1] + cpM.y * 2 * radius
};
var tgtCtrlPtIntn = tgtShape.intersectLine(tgtPos.x, tgtPos.y, tgtW, tgtH, cpProj.x, cpProj.y, 0);
if (closeEndACp) {
rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist);
rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist);
} else {
rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist;
rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist;
}
}
if (overlapping) {
// recalc endpts
this.findEndpoints(edge);
}
}
if (rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound') {
rs.allpts = [];
rs.allpts.push(rs.startX, rs.startY);
for (var b = 0; b + 1 < rs.ctrlpts.length; b += 2) {
// ctrl pt itself
rs.allpts.push(rs.ctrlpts[b], rs.ctrlpts[b + 1]);
// the midpt between ctrlpts as intermediate destination pts
if (b + 3 < rs.ctrlpts.length) {
rs.allpts.push((rs.ctrlpts[b] + rs.ctrlpts[b + 2]) / 2, (rs.ctrlpts[b + 1] + rs.ctrlpts[b + 3]) / 2);
}
}
rs.allpts.push(rs.endX, rs.endY);
var m, mt;
if (rs.ctrlpts.length / 2 % 2 === 0) {
m = rs.allpts.length / 2 - 1;
rs.midX = rs.allpts[m];
rs.midY = rs.allpts[m + 1];
} else {
m = rs.allpts.length / 2 - 3;
mt = 0.5;
rs.midX = math.qbezierAt(rs.allpts[m], rs.allpts[m + 2], rs.allpts[m + 4], mt);
rs.midY = math.qbezierAt(rs.allpts[m + 1], rs.allpts[m + 3], rs.allpts[m + 5], mt);
}
} else if (rs.edgeType === 'straight') {
// need to calc these after endpts
rs.allpts = [rs.startX, rs.startY, rs.endX, rs.endY];
// default midpt for labels etc
rs.midX = (rs.startX + rs.endX + rs.arrowStartX + rs.arrowEndX) / 4;
rs.midY = (rs.startY + rs.endY + rs.arrowStartY + rs.arrowEndY) / 4;
} else if (rs.edgeType === 'segments') {
rs.allpts = [];
rs.allpts.push(rs.startX, rs.startY);
rs.allpts.push.apply(rs.allpts, rs.segpts);
rs.allpts.push(rs.endX, rs.endY);
if (rs.segpts.length % 4 === 0) {
var i2 = rs.segpts.length / 2;
var i1 = i2 - 2;
rs.midX = (rs.segpts[i1] + rs.segpts[i2]) / 2;
rs.midY = (rs.segpts[i1 + 1] + rs.segpts[i2 + 1]) / 2;
} else {
var i1 = rs.segpts.length / 2 - 1;
rs.midX = rs.segpts[i1];
rs.midY = rs.segpts[i1 + 1];
}
}
this.storeEdgeProjections(edge);
this.calculateArrowAngles(edge);
} // if point cache miss
this.recalculateEdgeLabelProjections(edge);
this.calculateLabelAngles(edge);
} // for pair edges
} // for pair ids
for (var i = 0; i < haystackEdges.length; i++) {
var edge = haystackEdges[i];
var _p = edge._private;
var rscratch = _p.rscratch;
var rs = rscratch;
if (!rscratch.haystack) {
var angle = Math.random() * 2 * Math.PI;
rscratch.source = {
x: Math.cos(angle),
y: Math.sin(angle)
};
var angle = Math.random() * 2 * Math.PI;
rscratch.target = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
var src = _p.source;
var tgt = _p.target;
var srcPos = src.position();
var tgtPos = tgt.position();
var srcW = src.width();
var tgtW = tgt.width();
var srcH = src.height();
var tgtH = tgt.height();
var radius = edge.pstyle('haystack-radius').value;
var halfRadius = radius / 2; // b/c have to half width/height
rs.haystackPts = rs.allpts = [rs.source.x * srcW * halfRadius + srcPos.x, rs.source.y * srcH * halfRadius + srcPos.y, rs.target.x * tgtW * halfRadius + tgtPos.x, rs.target.y * tgtH * halfRadius + tgtPos.y];
rs.midX = (rs.allpts[0] + rs.allpts[2]) / 2;
rs.midY = (rs.allpts[1] + rs.allpts[3]) / 2;
// always override as haystack in case set to different type previously
rscratch.edgeType = rscratch.lastCurveStyle = 'haystack';
rscratch.haystack = true;
this.storeEdgeProjections(edge);
this.calculateArrowAngles(edge);
this.recalculateEdgeLabelProjections(edge);
this.calculateLabelAngles(edge);
}
};
function getPts(pts) {
var retPts = [];
if (pts == null) {
return;
}
for (var i = 0; i < pts.length; i += 2) {
var x = pts[i];
var y = pts[i + 1];
retPts.push({ x: x, y: y });
}
return retPts;
}
BRp.getSegmentPoints = function (edge) {
var rs = edge[0]._private.rscratch;
var type = rs.edgeType;
if (type === 'segments') {
return getPts(rs.segpts);
}
};
BRp.getControlPoints = function (edge) {
var rs = edge[0]._private.rscratch;
var type = rs.edgeType;
if (type === 'bezier' || type === 'multibezier' || type === 'self' || type === 'compound') {
return getPts(rs.ctrlpts);
}
};
BRp.getEdgeMidpoint = function (edge) {
var rs = edge[0]._private.rscratch;
return {
x: rs.midX,
y: rs.midY
};
};
module.exports = BRp;
/***/ }),
/* 114 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var BRp = {};
BRp.manualEndptToPx = function (node, prop) {
var r = this;
var npos = node.position();
var w = node.outerWidth();
var h = node.outerHeight();
if (prop.value.length === 2) {
var p = [prop.pfValue[0], prop.pfValue[1]];
if (prop.units[0] === '%') {
p[0] = p[0] * w;
}
if (prop.units[1] === '%') {
p[1] = p[1] * h;
}
p[0] += npos.x;
p[1] += npos.y;
return p;
} else {
var angle = prop.pfValue[0];
angle = -Math.PI / 2 + angle; // start at 12 o'clock
var l = 2 * Math.max(w, h);
var _p = [npos.x + Math.cos(angle) * l, npos.y + Math.sin(angle) * l];
return r.nodeShapes[this.getNodeShape(node)].intersectLine(npos.x, npos.y, w, h, _p[0], _p[1], 0);
}
};
BRp.findEndpoints = function (edge) {
var r = this;
var intersect = void 0;
var source = edge.source()[0];
var target = edge.target()[0];
var srcPos = source.position();
var tgtPos = target.position();
var tgtArShape = edge.pstyle('target-arrow-shape').value;
var srcArShape = edge.pstyle('source-arrow-shape').value;
var tgtDist = edge.pstyle('target-distance-from-node').pfValue;
var srcDist = edge.pstyle('source-distance-from-node').pfValue;
var rs = edge._private.rscratch;
var et = rs.edgeType;
var self = et === 'self' || et === 'compound';
var bezier = et === 'bezier' || et === 'multibezier' || self;
var multi = et !== 'bezier';
var lines = et === 'straight' || et === 'segments';
var segments = et === 'segments';
var hasEndpts = bezier || multi || lines;
var srcManEndpt = edge.pstyle('source-endpoint');
var srcManEndptVal = self ? 'outside-to-node' : srcManEndpt.value;
var tgtManEndpt = edge.pstyle('target-endpoint');
var tgtManEndptVal = self ? 'outside-to-node' : tgtManEndpt.value;
rs.srcManEndpt = srcManEndpt;
rs.tgtManEndpt = tgtManEndpt;
var p1 = void 0; // last known point of edge on target side
var p2 = void 0; // last known point of edge on source side
var p1_i = void 0; // point to intersect with target shape
var p2_i = void 0; // point to intersect with source shape
if (bezier) {
var cpStart = [rs.ctrlpts[0], rs.ctrlpts[1]];
var cpEnd = multi ? [rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1]] : cpStart;
p1 = cpEnd;
p2 = cpStart;
} else if (lines) {
var srcArrowFromPt = !segments ? [tgtPos.x, tgtPos.y] : rs.segpts.slice(0, 2);
var tgtArrowFromPt = !segments ? [srcPos.x, srcPos.y] : rs.segpts.slice(rs.segpts.length - 2);
p1 = tgtArrowFromPt;
p2 = srcArrowFromPt;
}
if (tgtManEndptVal === 'inside-to-node') {
intersect = [tgtPos.x, tgtPos.y];
} else if (tgtManEndpt.units) {
intersect = this.manualEndptToPx(target, tgtManEndpt);
} else if (tgtManEndptVal === 'outside-to-line') {
intersect = rs.tgtIntn; // use cached value from ctrlpt calc
} else {
if (tgtManEndptVal === 'outside-to-node') {
p1_i = p1;
} else if (tgtManEndptVal === 'outside-to-line') {
p1_i = [srcPos.x, srcPos.y];
}
intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(tgtPos.x, tgtPos.y, target.outerWidth(), target.outerHeight(), p1_i[0], p1_i[1], 0);
}
var arrowEnd = math.shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].spacing(edge) + tgtDist);
var edgeEnd = math.shortenIntersection(intersect, p1, r.arrowShapes[tgtArShape].gap(edge) + tgtDist);
rs.endX = edgeEnd[0];
rs.endY = edgeEnd[1];
rs.arrowEndX = arrowEnd[0];
rs.arrowEndY = arrowEnd[1];
if (srcManEndptVal === 'inside-to-node') {
intersect = [srcPos.x, srcPos.y];
} else if (srcManEndpt.units) {
intersect = this.manualEndptToPx(source, srcManEndpt);
} else if (srcManEndptVal === 'outside-to-line') {
intersect = rs.srcIntn; // use cached value from ctrlpt calc
} else {
if (srcManEndptVal === 'outside-to-node') {
p2_i = p2;
} else if (srcManEndptVal === 'outside-to-line') {
p2_i = [tgtPos.x, tgtPos.y];
}
intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(srcPos.x, srcPos.y, source.outerWidth(), source.outerHeight(), p2_i[0], p2_i[1], 0);
}
var arrowStart = math.shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].spacing(edge) + srcDist);
var edgeStart = math.shortenIntersection(intersect, p2, r.arrowShapes[srcArShape].gap(edge) + srcDist);
rs.startX = edgeStart[0];
rs.startY = edgeStart[1];
rs.arrowStartX = arrowStart[0];
rs.arrowStartY = arrowStart[1];
if (hasEndpts) {
if (!is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY)) {
rs.badLine = true;
} else {
rs.badLine = false;
}
}
};
BRp.getSourceEndpoint = function (edge) {
var rs = edge[0]._private.rscratch;
switch (rs.edgeType) {
case 'haystack':
return {
x: rs.haystackPts[0],
y: rs.haystackPts[1]
};
default:
return {
x: rs.arrowStartX,
y: rs.arrowStartY
};
}
};
BRp.getTargetEndpoint = function (edge) {
var rs = edge[0]._private.rscratch;
switch (rs.edgeType) {
case 'haystack':
return {
x: rs.haystackPts[2],
y: rs.haystackPts[3]
};
default:
return {
x: rs.arrowEndX,
y: rs.arrowEndY
};
}
};
module.exports = BRp;
/***/ }),
/* 115 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var BRp = {};
function pushBezierPts(r, edge, pts) {
var qbezierAt = function qbezierAt(p1, p2, p3, t) {
return math.qbezierAt(p1, p2, p3, t);
};
var _p = edge._private;
var bpts = _p.rstyle.bezierPts;
for (var i = 0; i < r.bezierProjPcts.length; i++) {
var p = r.bezierProjPcts[i];
bpts.push({
x: qbezierAt(pts[0], pts[2], pts[4], p),
y: qbezierAt(pts[1], pts[3], pts[5], p)
});
}
}
BRp.storeEdgeProjections = function (edge) {
var _p = edge._private;
var rs = _p.rscratch;
var et = rs.edgeType;
// clear the cached points state
_p.rstyle.bezierPts = null;
_p.rstyle.linePts = null;
_p.rstyle.haystackPts = null;
if (et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound') {
var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line
for (var i = 0; i + 5 < rs.allpts.length; i += 4) {
pushBezierPts(this, edge, rs.allpts.slice(i, i + 6));
}
} else if (et === 'segments') {
var lpts = _p.rstyle.linePts = [];
for (var i = 0; i + 1 < rs.allpts.length; i += 2) {
lpts.push({
x: rs.allpts[i],
y: rs.allpts[i + 1]
});
}
} else if (et === 'haystack') {
var hpts = rs.haystackPts;
_p.rstyle.haystackPts = [{ x: hpts[0], y: hpts[1] }, { x: hpts[2], y: hpts[3] }];
}
_p.rstyle.arrowWidth = this.getArrowWidth(edge.pstyle('width').pfValue, edge.pstyle('arrow-scale').value) * this.arrowShapeWidth;
};
BRp.recalculateEdgeProjections = function (edges) {
this.findEdgeControlPoints(edges);
};
module.exports = BRp;
/***/ }),
/* 116 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var BRp = {};
BRp.recalculateNodeLabelProjection = function (node) {
var content = node.pstyle('label').strValue;
if (is.emptyString(content)) {
return;
}
var textX, textY;
var _p = node._private;
var nodeWidth = node.width();
var nodeHeight = node.height();
var padding = node.padding();
var nodePos = node.position();
var textHalign = node.pstyle('text-halign').strValue;
var textValign = node.pstyle('text-valign').strValue;
var rs = _p.rscratch;
var rstyle = _p.rstyle;
switch (textHalign) {
case 'left':
textX = nodePos.x - nodeWidth / 2 - padding;
break;
case 'right':
textX = nodePos.x + nodeWidth / 2 + padding;
break;
default:
// e.g. center
textX = nodePos.x;
}
switch (textValign) {
case 'top':
textY = nodePos.y - nodeHeight / 2 - padding;
break;
case 'bottom':
textY = nodePos.y + nodeHeight / 2 + padding;
break;
default:
// e.g. middle
textY = nodePos.y;
}
rs.labelX = textX;
rs.labelY = textY;
rstyle.labelX = textX;
rstyle.labelY = textY;
this.applyLabelDimensions(node);
};
var lineAngleFromDelta = function lineAngleFromDelta(dx, dy) {
var angle = Math.atan(dy / dx);
if (dx === 0 && angle < 0) {
angle = angle * -1;
}
return angle;
};
var lineAngle = function lineAngle(p0, p1) {
var dx = p1.x - p0.x;
var dy = p1.y - p0.y;
return lineAngleFromDelta(dx, dy);
};
var bezierAngle = function bezierAngle(p0, p1, p2, t) {
var t0 = math.bound(0, t - 0.001, 1);
var t1 = math.bound(0, t + 0.001, 1);
var lp0 = math.qbezierPtAt(p0, p1, p2, t0);
var lp1 = math.qbezierPtAt(p0, p1, p2, t1);
return lineAngle(lp0, lp1);
};
BRp.recalculateEdgeLabelProjections = function (edge) {
var p;
var _p = edge._private;
var rs = _p.rscratch;
var r = this;
var content = {
mid: edge.pstyle('label').strValue,
source: edge.pstyle('source-label').strValue,
target: edge.pstyle('target-label').strValue
};
if (content.mid || content.source || content.target) {
// then we have to calculate...
} else {
return; // no labels => no calcs
}
// add center point to style so bounding box calculations can use it
//
p = {
x: rs.midX,
y: rs.midY
};
var setRs = function setRs(propName, prefix, value) {
util.setPrefixedProperty(_p.rscratch, propName, prefix, value);
util.setPrefixedProperty(_p.rstyle, propName, prefix, value);
};
setRs('labelX', null, p.x);
setRs('labelY', null, p.y);
var midAngle = lineAngleFromDelta(rs.midDispX, rs.midDispY);
setRs('labelAutoAngle', null, midAngle);
var createControlPointInfo = function createControlPointInfo() {
if (createControlPointInfo.cache) {
return createControlPointInfo.cache;
} // use cache so only 1x per edge
var ctrlpts = [];
// store each ctrlpt info init
for (var i = 0; i + 5 < rs.allpts.length; i += 4) {
var p0 = { x: rs.allpts[i], y: rs.allpts[i + 1] };
var p1 = { x: rs.allpts[i + 2], y: rs.allpts[i + 3] }; // ctrlpt
var p2 = { x: rs.allpts[i + 4], y: rs.allpts[i + 5] };
ctrlpts.push({
p0: p0,
p1: p1,
p2: p2,
startDist: 0,
length: 0,
segments: []
});
}
var bpts = _p.rstyle.bezierPts;
var nProjs = r.bezierProjPcts.length;
function addSegment(cp, p0, p1, t0, t1) {
var length = math.dist(p0, p1);
var prevSegment = cp.segments[cp.segments.length - 1];
var segment = {
p0: p0,
p1: p1,
t0: t0,
t1: t1,
startDist: prevSegment ? prevSegment.startDist + prevSegment.length : 0,
length: length
};
cp.segments.push(segment);
cp.length += length;
}
// update each ctrlpt with segment info
for (var i = 0; i < ctrlpts.length; i++) {
var cp = ctrlpts[i];
var prevCp = ctrlpts[i - 1];
if (prevCp) {
cp.startDist = prevCp.startDist + prevCp.length;
}
addSegment(cp, cp.p0, bpts[i * nProjs], 0, r.bezierProjPcts[0]); // first
for (var j = 0; j < nProjs - 1; j++) {
addSegment(cp, bpts[i * nProjs + j], bpts[i * nProjs + j + 1], r.bezierProjPcts[j], r.bezierProjPcts[j + 1]);
}
addSegment(cp, bpts[i * nProjs + nProjs - 1], cp.p2, r.bezierProjPcts[nProjs - 1], 1); // last
}
return createControlPointInfo.cache = ctrlpts;
};
var calculateEndProjection = function calculateEndProjection(prefix) {
var angle;
var isSrc = prefix === 'source';
if (!content[prefix]) {
return;
}
var offset = edge.pstyle(prefix + '-text-offset').pfValue;
switch (rs.edgeType) {
case 'self':
case 'compound':
case 'bezier':
case 'multibezier':
var cps = createControlPointInfo();
var selected;
var startDist = 0;
var totalDist = 0;
// find the segment we're on
for (var i = 0; i < cps.length; i++) {
var cp = cps[isSrc ? i : cps.length - 1 - i];
for (var j = 0; j < cp.segments.length; j++) {
var seg = cp.segments[isSrc ? j : cp.segments.length - 1 - j];
var lastSeg = i === cps.length - 1 && j === cp.segments.length - 1;
startDist = totalDist;
totalDist += seg.length;
if (totalDist >= offset || lastSeg) {
selected = { cp: cp, segment: seg };
break;
}
}
if (selected) {
break;
}
}
var cp = selected.cp;
var seg = selected.segment;
var tSegment = (offset - startDist) / seg.length;
var segDt = seg.t1 - seg.t0;
var t = isSrc ? seg.t0 + segDt * tSegment : seg.t1 - segDt * tSegment;
t = math.bound(0, t, 1);
p = math.qbezierPtAt(cp.p0, cp.p1, cp.p2, t);
angle = bezierAngle(cp.p0, cp.p1, cp.p2, t, p);
break;
case 'straight':
case 'segments':
case 'haystack':
var d = 0,
di,
d0;
var p0, p1;
var l = rs.allpts.length;
for (var i = 0; i + 3 < l; i += 2) {
if (isSrc) {
p0 = { x: rs.allpts[i], y: rs.allpts[i + 1] };
p1 = { x: rs.allpts[i + 2], y: rs.allpts[i + 3] };
} else {
p0 = { x: rs.allpts[l - 2 - i], y: rs.allpts[l - 1 - i] };
p1 = { x: rs.allpts[l - 4 - i], y: rs.allpts[l - 3 - i] };
}
di = math.dist(p0, p1);
d0 = d;
d += di;
if (d >= offset) {
break;
}
}
var pD = offset - d0;
var t = pD / di;
t = math.bound(0, t, 1);
p = math.lineAt(p0, p1, t);
angle = lineAngle(p0, p1);
break;
}
setRs('labelX', prefix, p.x);
setRs('labelY', prefix, p.y);
setRs('labelAutoAngle', prefix, angle);
};
calculateEndProjection('source');
calculateEndProjection('target');
this.applyLabelDimensions(edge);
};
BRp.applyLabelDimensions = function (ele) {
this.applyPrefixedLabelDimensions(ele);
if (ele.isEdge()) {
this.applyPrefixedLabelDimensions(ele, 'source');
this.applyPrefixedLabelDimensions(ele, 'target');
}
};
BRp.applyPrefixedLabelDimensions = function (ele, prefix) {
var _p = ele._private;
var text = this.getLabelText(ele, prefix);
var labelDims = this.calculateLabelDimensions(ele, text);
util.setPrefixedProperty(_p.rstyle, 'labelWidth', prefix, labelDims.width);
util.setPrefixedProperty(_p.rscratch, 'labelWidth', prefix, labelDims.width);
util.setPrefixedProperty(_p.rstyle, 'labelHeight', prefix, labelDims.height);
util.setPrefixedProperty(_p.rscratch, 'labelHeight', prefix, labelDims.height);
};
BRp.getLabelText = function (ele, prefix) {
var _p = ele._private;
var pfd = prefix ? prefix + '-' : '';
var text = ele.pstyle(pfd + 'label').strValue;
var textTransform = ele.pstyle('text-transform').value;
var rscratch = function rscratch(propName, value) {
if (value) {
util.setPrefixedProperty(_p.rscratch, propName, prefix, value);
return value;
} else {
return util.getPrefixedProperty(_p.rscratch, propName, prefix);
}
};
// for empty text, skip all processing
if (!text) {
return '';
}
if (textTransform == 'none') {
// passthrough
} else if (textTransform == 'uppercase') {
text = text.toUpperCase();
} else if (textTransform == 'lowercase') {
text = text.toLowerCase();
}
var wrapStyle = ele.pstyle('text-wrap').value;
if (wrapStyle === 'wrap') {
//console.log('wrap');
var labelKey = rscratch('labelKey');
// save recalc if the label is the same as before
if (labelKey && rscratch('labelWrapKey') === labelKey) {
// console.log('wrap cache hit');
return rscratch('labelWrapCachedText');
}
// console.log('wrap cache miss');
var lines = text.split('\n');
var maxW = ele.pstyle('text-max-width').pfValue;
var wrappedLines = [];
for (var l = 0; l < lines.length; l++) {
var line = lines[l];
var lineDims = this.calculateLabelDimensions(ele, line, 'line=' + line);
var lineW = lineDims.width;
if (lineW > maxW) {
// line is too long
var words = line.split(/\s+/); // NB: assume collapsed whitespace into single space
var subline = '';
for (var w = 0; w < words.length; w++) {
var word = words[w];
var testLine = subline.length === 0 ? word : subline + ' ' + word;
var testDims = this.calculateLabelDimensions(ele, testLine, 'testLine=' + testLine);
var testW = testDims.width;
if (testW <= maxW) {
// word fits on current line
subline += word + ' ';
} else {
// word starts new line
wrappedLines.push(subline);
subline = word + ' ';
}
}
// if there's remaining text, put it in a wrapped line
if (!subline.match(/^\s+$/)) {
wrappedLines.push(subline);
}
} else {
// line is already short enough
wrappedLines.push(line);
}
} // for
rscratch('labelWrapCachedLines', wrappedLines);
text = rscratch('labelWrapCachedText', wrappedLines.join('\n'));
rscratch('labelWrapKey', labelKey);
// console.log(text)
} else if (wrapStyle === 'ellipsis') {
var maxW = ele.pstyle('text-max-width').pfValue;
var ellipsized = '';
var ellipsis = '\u2026';
var incLastCh = false;
for (var i = 0; i < text.length; i++) {
var widthWithNextCh = this.calculateLabelDimensions(ele, ellipsized + text[i] + ellipsis).width;
if (widthWithNextCh > maxW) {
break;
}
ellipsized += text[i];
if (i === text.length - 1) {
incLastCh = true;
}
}
if (!incLastCh) {
ellipsized += ellipsis;
}
return ellipsized;
} // if ellipsize
return text;
};
BRp.calculateLabelDimensions = function (ele, text, extraKey) {
var r = this;
var cacheKey = ele._private.labelStyleKey + '$@$' + text;
if (extraKey) {
cacheKey += '$@$' + extraKey;
}
var cache = r.labelDimCache || (r.labelDimCache = {});
if (cache[cacheKey]) {
return cache[cacheKey];
}
var sizeMult = 1; // increase the scale to increase accuracy w.r.t. zoomed text
var fStyle = ele.pstyle('font-style').strValue;
var size = sizeMult * ele.pstyle('font-size').pfValue + 'px';
var family = ele.pstyle('font-family').strValue;
var weight = ele.pstyle('font-weight').strValue;
var div = this.labelCalcDiv;
if (!div) {
div = this.labelCalcDiv = document.createElement('div'); // eslint-disable-line no-undef
document.body.appendChild(div); // eslint-disable-line no-undef
}
var ds = div.style;
// from ele style
ds.fontFamily = family;
ds.fontStyle = fStyle;
ds.fontSize = size;
ds.fontWeight = weight;
// forced style
ds.position = 'absolute';
ds.left = '-9999px';
ds.top = '-9999px';
ds.zIndex = '-1';
ds.visibility = 'hidden';
ds.pointerEvents = 'none';
ds.padding = '0';
ds.lineHeight = '1';
if (ele.pstyle('text-wrap').value === 'wrap') {
ds.whiteSpace = 'pre'; // so newlines are taken into account
} else {
ds.whiteSpace = 'normal';
}
// put label content in div
div.textContent = text;
cache[cacheKey] = {
width: Math.ceil(div.clientWidth / sizeMult),
height: Math.ceil(div.clientHeight / sizeMult)
};
return cache[cacheKey];
};
BRp.calculateLabelAngles = function (ele) {
var _p = ele._private;
var rs = _p.rscratch;
var isEdge = ele.isEdge();
var rot = ele.pstyle('text-rotation');
var rotStr = rot.strValue;
if (rotStr === 'none') {
rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0;
} else if (isEdge && rotStr === 'autorotate') {
rs.labelAngle = rs.labelAutoAngle;
rs.sourceLabelAngle = rs.sourceLabelAutoAngle;
rs.targetLabelAngle = rs.targetLabelAutoAngle;
} else if (rotStr === 'autorotate') {
rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = 0;
} else {
rs.labelAngle = rs.sourceLabelAngle = rs.targetLabelAngle = rot.pfValue;
}
};
module.exports = BRp;
/***/ }),
/* 117 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var BRp = {};
BRp.getNodeShape = function (node) {
var r = this;
var shape = node.pstyle('shape').value;
if (node.isParent()) {
if (shape === 'rectangle' || shape === 'roundrectangle' || shape === 'cutrectangle' || shape === 'barrel') {
return shape;
} else {
return 'rectangle';
}
}
if (shape === 'polygon') {
var points = node.pstyle('shape-polygon-points').value;
return r.nodeShapes.makePolygon(points).name;
}
return shape;
};
module.exports = BRp;
/***/ }),
/* 118 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var BRp = {};
BRp.registerCalculationListeners = function () {
var cy = this.cy;
var elesToUpdate = cy.collection();
var r = this;
var enqueue = function enqueue(eles, e) {
var dirtyStyleCaches = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
elesToUpdate.merge(eles);
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var _p = ele._private;
var rstyle = _p.rstyle;
if (dirtyStyleCaches) {
rstyle.clean = false;
_p.bbCache = null;
}
var evts = rstyle.dirtyEvents = rstyle.dirtyEvents || { length: 0 };
if (!evts[e.type]) {
evts[e.type] = true;
evts.length++;
}
}
};
r.binder(cy)
// nodes
.on('position.* style.* free.* bounds.*', 'node', function onDirtyModNode(e) {
var node = e.target;
enqueue(node, e);
enqueue(node.connectedEdges(), e);
}).on('add.*', 'node', function onDirtyAddNode(e) {
var ele = e.target;
enqueue(ele, e);
}).on('background.*', 'node', function onDirtyBgNode(e) {
var ele = e.target;
enqueue(ele, e, false);
})
// edges
.on('add.* style.*', 'edge', function onDirtyEdge(e) {
var edge = e.target;
enqueue(edge, e);
enqueue(edge.parallelEdges(), e);
}).on('remove.*', 'edge', function onDirtyRemoveEdge(e) {
var edge = e.target;
var pEdges = edge.parallelEdges();
for (var i = 0; i < pEdges.length; i++) {
var pEdge = pEdges[i];
if (!pEdge.removed()) {
enqueue(pEdge, e);
}
}
})
// manual dirtying
.on('dirty.*', 'node', function onDirtyEle(e) {
var ele = e.target;
enqueue(ele, e);
});
var updateEleCalcs = function updateEleCalcs(willDraw) {
if (willDraw) {
var fns = r.onUpdateEleCalcsFns;
if (fns) {
for (var i = 0; i < fns.length; i++) {
var fn = fns[i];
fn(willDraw, elesToUpdate);
}
}
r.recalculateRenderedStyle(elesToUpdate, false);
for (var i = 0; i < elesToUpdate.length; i++) {
elesToUpdate[i]._private.rstyle.dirtyEvents = null;
}
elesToUpdate = cy.collection();
}
};
r.beforeRender(updateEleCalcs, r.beforeRenderPriorities.eleCalcs);
};
BRp.onUpdateEleCalcs = function (fn) {
var fns = this.onUpdateEleCalcsFns = this.onUpdateEleCalcsFns || [];
fns.push(fn);
};
BRp.recalculateRenderedStyle = function (eles, useCache) {
var edges = [];
var nodes = [];
// the renderer can't be used for calcs when destroyed, e.g. ele.boundingBox()
if (this.destroyed) {
return;
}
// use cache by default for perf
if (useCache === undefined) {
useCache = true;
}
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var _p = ele._private;
var rstyle = _p.rstyle;
// only update if dirty and in graph
if (useCache && rstyle.clean || ele.removed()) {
continue;
}
// only update if not display: none
if (ele.pstyle('display').value === 'none') {
continue;
}
if (_p.group === 'nodes') {
nodes.push(ele);
} else {
// edges
edges.push(ele);
}
rstyle.clean = true;
// rstyle.dirtyEvents = null;
}
// update node data from projections
for (var i = 0; i < nodes.length; i++) {
var ele = nodes[i];
var _p = ele._private;
var rstyle = _p.rstyle;
var pos = ele.position();
this.recalculateNodeLabelProjection(ele);
rstyle.nodeX = pos.x;
rstyle.nodeY = pos.y;
rstyle.nodeW = ele.pstyle('width').pfValue;
rstyle.nodeH = ele.pstyle('height').pfValue;
}
this.recalculateEdgeProjections(edges);
// update edge data from projections
for (var i = 0; i < edges.length; i++) {
var ele = edges[i];
var _p = ele._private;
var rstyle = _p.rstyle;
var rs = _p.rscratch;
this.recalculateEdgeLabelProjections(ele);
// update rstyle positions
rstyle.srcX = rs.arrowStartX;
rstyle.srcY = rs.arrowStartY;
rstyle.tgtX = rs.arrowEndX;
rstyle.tgtY = rs.arrowEndY;
rstyle.midX = rs.midX;
rstyle.midY = rs.midY;
rstyle.labelAngle = rs.labelAngle;
rstyle.sourceLabelAngle = rs.sourceLabelAngle;
rstyle.targetLabelAngle = rs.targetLabelAngle;
}
};
module.exports = BRp;
/***/ }),
/* 119 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var zIndexSort = __webpack_require__(17);
var BRp = {};
BRp.updateCachedGrabbedEles = function () {
var eles = this.cachedZSortedEles;
if (!eles) {
// just let this be recalculated on the next z sort tick
return;
}
eles.drag = [];
eles.nondrag = [];
var grabTargets = [];
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var rs = ele._private.rscratch;
if (ele.grabbed() && !ele.isParent()) {
grabTargets.push(ele);
} else if (rs.inDragLayer) {
eles.drag.push(ele);
} else {
eles.nondrag.push(ele);
}
}
// put the grab target nodes last so it's on top of its neighbourhood
for (var i = 0; i < grabTargets.length; i++) {
var ele = grabTargets[i];
eles.drag.push(ele);
}
};
BRp.invalidateCachedZSortedEles = function () {
this.cachedZSortedEles = null;
};
BRp.getCachedZSortedEles = function (forceRecalc) {
if (forceRecalc || !this.cachedZSortedEles) {
//console.time('cachezorder')
var eles = this.cy.mutableElements().toArray();
eles.sort(zIndexSort);
eles.interactive = eles.filter(function (ele) {
return ele.interactive();
});
this.cachedZSortedEles = eles;
this.updateCachedGrabbedEles();
} else {
eles = this.cachedZSortedEles;
}
return eles;
};
module.exports = BRp;
/***/ }),
/* 120 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var BRp = {};
BRp.getCachedImage = function (url, crossOrigin, onLoad) {
var r = this;
var imageCache = r.imageCache = r.imageCache || {};
var cache = imageCache[url];
if (cache) {
if (!cache.image.complete) {
cache.image.addEventListener('load', onLoad);
}
return cache.image;
} else {
cache = imageCache[url] = imageCache[url] || {};
var image = cache.image = new Image(); // eslint-disable-line no-undef
image.addEventListener('load', onLoad);
image.addEventListener('error', function () {
image.error = true;
});
// #1582 safari doesn't load data uris with crossOrigin properly
// https://bugs.webkit.org/show_bug.cgi?id=123978
var dataUriPrefix = 'data:';
var isDataUri = url.substring(0, dataUriPrefix.length).toLowerCase() === dataUriPrefix;
if (!isDataUri) {
image.crossOrigin = crossOrigin; // prevent tainted canvas
}
image.src = url;
return image;
}
};
module.exports = BRp;
/***/ }),
/* 121 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var Event = __webpack_require__(16);
var BRp = {};
BRp.registerBinding = function (target, event, handler, useCapture) {
var args = Array.prototype.slice.apply(arguments, [1]); // copy
var b = this.binder(target);
return b.on.apply(b, args);
};
BRp.binder = function (tgt) {
var r = this;
var tgtIsDom = tgt === window || tgt === document || tgt === document.body || is.domElement(tgt);
if (r.supportsPassiveEvents == null) {
// from https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function get() {
supportsPassive = true;
}
});
window.addEventListener('test', null, opts);
} catch (err) {}
r.supportsPassiveEvents = supportsPassive;
}
var on = function on(event, handler, useCapture) {
var args = Array.prototype.slice.call(arguments);
if (tgtIsDom && r.supportsPassiveEvents) {
// replace useCapture w/ opts obj
args[2] = {
capture: useCapture != null ? useCapture : false,
passive: false,
once: false
};
}
r.bindings.push({
target: tgt,
args: args
});
(tgt.addEventListener || tgt.on).apply(tgt, args);
return this;
};
return {
on: on,
addEventListener: on,
addListener: on,
bind: on
};
};
BRp.nodeIsDraggable = function (node) {
return node && node.isNode() && !node.locked() && node.grabbable();
};
BRp.nodeIsGrabbable = function (node) {
return this.nodeIsDraggable(node) && node.interactive();
};
BRp.load = function () {
var r = this;
var triggerEvents = function triggerEvents(target, names, e, props) {
if (target == null) {
target = r.cy;
}
for (var i = 0; i < names.length; i++) {
var name = names[i];
target.emit(util.extend({ originalEvent: e, type: name }, props));
}
};
var isMultSelKeyDown = function isMultSelKeyDown(e) {
return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey
};
var allowPanningPassthrough = function allowPanningPassthrough(down, downs) {
var allowPassthrough = true;
if (r.cy.hasCompoundNodes() && down && down.isEdge()) {
// a compound node below the edge => no passthrough panning
for (var i = 0; downs && i < downs.length; i++) {
var down = downs[i];
if (down.isNode() && down.isParent()) {
allowPassthrough = false;
break;
}
}
} else {
allowPassthrough = true;
}
return allowPassthrough;
};
var getDragListIds = function getDragListIds(opts) {
var listHasId;
if (opts.addToList && r.cy.hasCompoundNodes()) {
// only needed for compound graphs
if (!opts.addToList.hasId) {
// build ids lookup if doesn't already exist
opts.addToList.hasId = {};
for (var i = 0; i < opts.addToList.length; i++) {
var ele = opts.addToList[i];
opts.addToList.hasId[ele.id()] = true;
}
}
listHasId = opts.addToList.hasId;
}
return listHasId || {};
};
var setGrabbed = function setGrabbed(ele) {
ele[0]._private.grabbed = true;
};
var setFreed = function setFreed(ele) {
ele[0]._private.grabbed = false;
};
var setInDragLayer = function setInDragLayer(ele) {
ele[0]._private.rscratch.inDragLayer = true;
};
var setOutDragLayer = function setOutDragLayer(ele) {
ele[0]._private.rscratch.inDragLayer = false;
};
var setGrabTarget = function setGrabTarget(ele) {
ele[0]._private.rscratch.isGrabTarget = true;
};
var removeGrabTarget = function removeGrabTarget(ele) {
ele[0]._private.rscratch.isGrabTarget = false;
};
var addToDragList = function addToDragList(ele, opts) {
var listHasId = getDragListIds(opts);
if (!listHasId[ele.id()]) {
opts.addToList.push(ele);
listHasId[ele.id()] = true;
setGrabbed(ele);
}
};
// helper function to determine which child nodes and inner edges
// of a compound node to be dragged as well as the grabbed and selected nodes
var addDescendantsToDrag = function addDescendantsToDrag(node, opts) {
if (!node.cy().hasCompoundNodes()) {
return;
}
if (opts.inDragLayer == null && opts.addToList == null) {
return;
} // nothing to do
var innerNodes = node.descendants();
if (opts.inDragLayer) {
innerNodes.forEach(setInDragLayer);
innerNodes.connectedEdges().forEach(setInDragLayer);
}
if (opts.addToList) {
innerNodes.forEach(function (ele) {
addToDragList(ele, opts);
});
}
};
// adds the given nodes and its neighbourhood to the drag layer
var addNodesToDrag = function addNodesToDrag(nodes, opts) {
opts = opts || {};
var hasCompoundNodes = nodes.cy().hasCompoundNodes();
if (opts.inDragLayer) {
nodes.forEach(setInDragLayer);
nodes.neighborhood().stdFilter(function (ele) {
return !hasCompoundNodes || ele.isEdge();
}).forEach(setInDragLayer);
}
if (opts.addToList) {
nodes.forEach(function (ele) {
addToDragList(ele, opts);
});
}
addDescendantsToDrag(nodes, opts); // always add to drag
// also add nodes and edges related to the topmost ancestor
updateAncestorsInDragLayer(nodes, {
inDragLayer: opts.inDragLayer
});
r.updateCachedGrabbedEles();
};
var addNodeToDrag = addNodesToDrag;
var freeDraggedElements = function freeDraggedElements(grabbedEles) {
if (!grabbedEles) {
return;
}
grabbedEles.hasId = {}; // clear the id list
// just go over all elements rather than doing a bunch of (possibly expensive) traversals
r.getCachedZSortedEles().forEach(function (ele) {
setFreed(ele);
setOutDragLayer(ele);
removeGrabTarget(ele);
});
r.updateCachedGrabbedEles();
};
// helper function to determine which ancestor nodes and edges should go
// to the drag layer (or should be removed from drag layer).
var updateAncestorsInDragLayer = function updateAncestorsInDragLayer(node, opts) {
if (opts.inDragLayer == null && opts.addToList == null) {
return;
} // nothing to do
if (!node.cy().hasCompoundNodes()) {
return;
}
// find top-level parent
var parent = node.ancestors().orphans();
// no parent node: no nodes to add to the drag layer
if (parent.same(node)) {
return;
}
var nodes = parent.descendants().spawnSelf().merge(parent).unmerge(node).unmerge(node.descendants());
var edges = nodes.connectedEdges();
if (opts.inDragLayer) {
edges.forEach(setInDragLayer);
nodes.forEach(setInDragLayer);
}
if (opts.addToList) {
nodes.forEach(function (ele) {
addToDragList(ele, opts);
});
}
};
var blurActiveDomElement = function blurActiveDomElement() {
if (document.activeElement != null && document.activeElement.blur != null) {
document.activeElement.blur();
}
};
var haveMutationsApi = typeof MutationObserver !== 'undefined';
// watch for when the cy container is removed from the dom
if (haveMutationsApi) {
r.removeObserver = new MutationObserver(function (mutns) {
// eslint-disable-line no-undef
for (var i = 0; i < mutns.length; i++) {
var mutn = mutns[i];
var rNodes = mutn.removedNodes;
if (rNodes) {
for (var j = 0; j < rNodes.length; j++) {
var rNode = rNodes[j];
if (rNode === r.container) {
r.destroy();
break;
}
}
}
}
});
if (r.container.parentNode) {
r.removeObserver.observe(r.container.parentNode, { childList: true });
}
} else {
r.registerBinding(r.container, 'DOMNodeRemoved', function (e) {
r.destroy();
});
}
var onResize = util.debounce(function () {
r.cy.resize();
}, 100);
if (haveMutationsApi) {
r.styleObserver = new MutationObserver(onResize); // eslint-disable-line no-undef
r.styleObserver.observe(r.container, { attributes: true });
}
// auto resize
r.registerBinding(window, 'resize', onResize); // eslint-disable-line no-undef
var forEachUp = function forEachUp(domEle, fn) {
while (domEle != null) {
fn(domEle);
domEle = domEle.parentNode;
}
};
var invalidateCoords = function invalidateCoords() {
r.invalidateContainerClientCoordsCache();
};
forEachUp(r.container, function (domEle) {
r.registerBinding(domEle, 'transitionend', invalidateCoords);
r.registerBinding(domEle, 'animationend', invalidateCoords);
r.registerBinding(domEle, 'scroll', invalidateCoords);
});
// stop right click menu from appearing on cy
r.registerBinding(r.container, 'contextmenu', function (e) {
e.preventDefault();
});
var inBoxSelection = function inBoxSelection() {
return r.selection[4] !== 0;
};
var eventInContainer = function eventInContainer(e) {
// save cycles if mouse events aren't to be captured
var containerPageCoords = r.findContainerClientCoords();
var x = containerPageCoords[0];
var y = containerPageCoords[1];
var width = containerPageCoords[2];
var height = containerPageCoords[3];
var positions = e.touches ? e.touches : [e];
var atLeastOnePosInside = false;
for (var i = 0; i < positions.length; i++) {
var p = positions[i];
if (x <= p.clientX && p.clientX <= x + width && y <= p.clientY && p.clientY <= y + height) {
atLeastOnePosInside = true;
break;
}
}
if (!atLeastOnePosInside) {
return false;
}
var container = r.container;
var target = e.target;
var tParent = target.parentNode;
var containerIsTarget = false;
while (tParent) {
if (tParent === container) {
containerIsTarget = true;
break;
}
tParent = tParent.parentNode;
}
if (!containerIsTarget) {
return false;
} // if target is outisde cy container, then this event is not for us
return true;
};
// Primary key
r.registerBinding(r.container, 'mousedown', function mousedownHandler(e) {
if (!eventInContainer(e)) {
return;
}
e.preventDefault();
blurActiveDomElement();
r.hoverData.capture = true;
r.hoverData.which = e.which;
var cy = r.cy;
var gpos = [e.clientX, e.clientY];
var pos = r.projectIntoViewport(gpos[0], gpos[1]);
var select = r.selection;
var nears = r.findNearestElements(pos[0], pos[1], true, false);
var near = nears[0];
var draggedElements = r.dragData.possibleDragElements;
r.hoverData.mdownPos = pos;
r.hoverData.mdownGPos = gpos;
var checkForTaphold = function checkForTaphold() {
r.hoverData.tapholdCancelled = false;
clearTimeout(r.hoverData.tapholdTimeout);
r.hoverData.tapholdTimeout = setTimeout(function () {
if (r.hoverData.tapholdCancelled) {
return;
} else {
var ele = r.hoverData.down;
if (ele) {
ele.emit({
originalEvent: e,
type: 'taphold',
position: { x: pos[0], y: pos[1] }
});
} else {
cy.emit({
originalEvent: e,
type: 'taphold',
position: { x: pos[0], y: pos[1] }
});
}
}
}, r.tapholdDuration);
};
// Right click button
if (e.which == 3) {
r.hoverData.cxtStarted = true;
var cxtEvt = {
originalEvent: e,
type: 'cxttapstart',
position: { x: pos[0], y: pos[1] }
};
if (near) {
near.activate();
near.emit(cxtEvt);
r.hoverData.down = near;
} else {
cy.emit(cxtEvt);
}
r.hoverData.downTime = new Date().getTime();
r.hoverData.cxtDragged = false;
// Primary button
} else if (e.which == 1) {
if (near) {
near.activate();
}
// Element dragging
{
// If something is under the cursor and it is draggable, prepare to grab it
if (near != null) {
if (r.nodeIsGrabbable(near)) {
var makeEvent = function makeEvent(type) {
return {
originalEvent: e,
type: type,
position: { x: pos[0], y: pos[1] }
};
};
var triggerGrab = function triggerGrab(ele) {
ele.emit(makeEvent('grab'));
};
setGrabTarget(near);
if (!near.selected()) {
draggedElements = r.dragData.possibleDragElements = [];
addNodeToDrag(near, { addToList: draggedElements });
near.emit(makeEvent('grabon')).emit(makeEvent('grab'));
} else {
draggedElements = r.dragData.possibleDragElements = [];
var selectedNodes = cy.$(function (ele) {
return ele.isNode() && ele.selected() && r.nodeIsGrabbable(ele);
});
addNodesToDrag(selectedNodes, { addToList: draggedElements });
near.emit(makeEvent('grabon'));
selectedNodes.forEach(triggerGrab);
}
r.redrawHint('eles', true);
r.redrawHint('drag', true);
}
}
r.hoverData.down = near;
r.hoverData.downs = nears;
r.hoverData.downTime = new Date().getTime();
}
triggerEvents(near, ['mousedown', 'tapstart', 'vmousedown'], e, {
position: { x: pos[0], y: pos[1] }
});
if (near == null) {
select[4] = 1;
r.data.bgActivePosistion = {
x: pos[0],
y: pos[1]
};
r.redrawHint('select', true);
r.redraw();
} else if (near.isEdge()) {
select[4] = 1; // for future pan
}
checkForTaphold();
}
// Initialize selection box coordinates
select[0] = select[2] = pos[0];
select[1] = select[3] = pos[1];
}, false);
r.registerBinding(window, 'mousemove', function mousemoveHandler(e) {
// eslint-disable-line no-undef
var capture = r.hoverData.capture;
if (!capture && !eventInContainer(e)) {
return;
}
var preventDefault = false;
var cy = r.cy;
var zoom = cy.zoom();
var gpos = [e.clientX, e.clientY];
var pos = r.projectIntoViewport(gpos[0], gpos[1]);
var mdownPos = r.hoverData.mdownPos;
var mdownGPos = r.hoverData.mdownGPos;
var select = r.selection;
var near = null;
if (!r.hoverData.draggingEles && !r.hoverData.dragging && !r.hoverData.selecting) {
near = r.findNearestElement(pos[0], pos[1], true, false);
}
var last = r.hoverData.last;
var down = r.hoverData.down;
var disp = [pos[0] - select[2], pos[1] - select[3]];
var draggedElements = r.dragData.possibleDragElements;
var isOverThresholdDrag;
if (mdownGPos) {
var dx = gpos[0] - mdownGPos[0];
var dx2 = dx * dx;
var dy = gpos[1] - mdownGPos[1];
var dy2 = dy * dy;
var dist2 = dx2 + dy2;
r.hoverData.isOverThresholdDrag = isOverThresholdDrag = dist2 >= r.desktopTapThreshold2;
}
var multSelKeyDown = isMultSelKeyDown(e);
if (isOverThresholdDrag) {
r.hoverData.tapholdCancelled = true;
}
var updateDragDelta = function updateDragDelta() {
var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];
if (dragDelta.length === 0) {
dragDelta.push(disp[0]);
dragDelta.push(disp[1]);
} else {
dragDelta[0] += disp[0];
dragDelta[1] += disp[1];
}
};
preventDefault = true;
triggerEvents(near, ['mousemove', 'vmousemove', 'tapdrag'], e, {
position: { x: pos[0], y: pos[1] }
});
var goIntoBoxMode = function goIntoBoxMode() {
r.data.bgActivePosistion = undefined;
if (!r.hoverData.selecting) {
cy.emit('boxstart');
}
select[4] = 1;
r.hoverData.selecting = true;
r.redrawHint('select', true);
r.redraw();
};
// trigger context drag if rmouse down
if (r.hoverData.which === 3) {
// but only if over threshold
if (isOverThresholdDrag) {
var cxtEvt = {
originalEvent: e,
type: 'cxtdrag',
position: { x: pos[0], y: pos[1] }
};
if (down) {
down.emit(cxtEvt);
} else {
cy.emit(cxtEvt);
}
r.hoverData.cxtDragged = true;
if (!r.hoverData.cxtOver || near !== r.hoverData.cxtOver) {
if (r.hoverData.cxtOver) {
r.hoverData.cxtOver.emit({
originalEvent: e,
type: 'cxtdragout',
position: { x: pos[0], y: pos[1] }
});
}
r.hoverData.cxtOver = near;
if (near) {
near.emit({
originalEvent: e,
type: 'cxtdragover',
position: { x: pos[0], y: pos[1] }
});
}
}
}
// Check if we are drag panning the entire graph
} else if (r.hoverData.dragging) {
preventDefault = true;
if (cy.panningEnabled() && cy.userPanningEnabled()) {
var deltaP;
if (r.hoverData.justStartedPan) {
var mdPos = r.hoverData.mdownPos;
deltaP = {
x: (pos[0] - mdPos[0]) * zoom,
y: (pos[1] - mdPos[1]) * zoom
};
r.hoverData.justStartedPan = false;
} else {
deltaP = {
x: disp[0] * zoom,
y: disp[1] * zoom
};
}
cy.panBy(deltaP);
r.hoverData.dragged = true;
}
// Needs reproject due to pan changing viewport
pos = r.projectIntoViewport(e.clientX, e.clientY);
// Checks primary button down & out of time & mouse not moved much
} else if (select[4] == 1 && (down == null || down.isEdge())) {
if (isOverThresholdDrag) {
if (!r.hoverData.dragging && cy.boxSelectionEnabled() && (multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled())) {
goIntoBoxMode();
} else if (!r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled()) {
var allowPassthrough = allowPanningPassthrough(down, r.hoverData.downs);
if (allowPassthrough) {
r.hoverData.dragging = true;
r.hoverData.justStartedPan = true;
select[4] = 0;
r.data.bgActivePosistion = math.array2point(mdownPos);
r.redrawHint('select', true);
r.redraw();
}
}
if (down && down.isEdge() && down.active()) {
down.unactivate();
}
}
} else {
if (down && down.isEdge() && down.active()) {
down.unactivate();
}
if ((!down || !down.grabbed()) && near != last) {
if (last) {
triggerEvents(last, ['mouseout', 'tapdragout'], e, {
position: { x: pos[0], y: pos[1] }
});
}
if (near) {
triggerEvents(near, ['mouseover', 'tapdragover'], e, {
position: { x: pos[0], y: pos[1] }
});
}
r.hoverData.last = near;
}
if (down) {
if (isOverThresholdDrag) {
// then we can take action
if (cy.boxSelectionEnabled() && multSelKeyDown) {
// then selection overrides
if (down && down.grabbed()) {
freeDraggedElements(draggedElements);
down.emit('free');
}
goIntoBoxMode();
} else if (down && down.grabbed() && r.nodeIsDraggable(down)) {
// drag node
var justStartedDrag = !r.dragData.didDrag;
if (justStartedDrag) {
r.redrawHint('eles', true);
}
r.dragData.didDrag = true; // indicate that we actually did drag the node
var toTrigger = [];
// now, add the elements to the drag layer if not done already
if (!r.hoverData.draggingEles) {
addNodesToDrag(cy.collection(draggedElements), { inDragLayer: true });
}
for (var i = 0; i < draggedElements.length; i++) {
var dEle = draggedElements[i];
// Locked nodes not draggable, as well as non-visible nodes
if (r.nodeIsDraggable(dEle) && dEle.grabbed()) {
var dPos = dEle.position();
toTrigger.push(dEle);
if (is.number(disp[0]) && is.number(disp[1])) {
dPos.x += disp[0];
dPos.y += disp[1];
if (justStartedDrag) {
var dragDelta = r.hoverData.dragDelta;
if (dragDelta && is.number(dragDelta[0]) && is.number(dragDelta[1])) {
dPos.x += dragDelta[0];
dPos.y += dragDelta[1];
}
}
}
}
}
r.hoverData.draggingEles = true;
var tcol = cy.collection(toTrigger);
tcol.dirtyCompoundBoundsCache();
tcol.emit('position drag');
r.redrawHint('drag', true);
r.redraw();
}
} else {
// otherwise save drag delta for when we actually start dragging so the relative grab pos is constant
updateDragDelta();
}
}
// prevent the dragging from triggering text selection on the page
preventDefault = true;
}
select[2] = pos[0];select[3] = pos[1];
if (preventDefault) {
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
return false;
}
}, false);
r.registerBinding(window, 'mouseup', function mouseupHandler(e) {
// eslint-disable-line no-undef
var capture = r.hoverData.capture;
if (!capture) {
return;
}
r.hoverData.capture = false;
var cy = r.cy;var pos = r.projectIntoViewport(e.clientX, e.clientY);var select = r.selection;
var near = r.findNearestElement(pos[0], pos[1], true, false);
var draggedElements = r.dragData.possibleDragElements;var down = r.hoverData.down;
var multSelKeyDown = isMultSelKeyDown(e);
if (r.data.bgActivePosistion) {
r.redrawHint('select', true);
r.redraw();
}
r.hoverData.tapholdCancelled = true;
r.data.bgActivePosistion = undefined; // not active bg now
if (down) {
down.unactivate();
}
if (r.hoverData.which === 3) {
var cxtEvt = {
originalEvent: e,
type: 'cxttapend',
position: { x: pos[0], y: pos[1] }
};
if (down) {
down.emit(cxtEvt);
} else {
cy.emit(cxtEvt);
}
if (!r.hoverData.cxtDragged) {
var cxtTap = {
originalEvent: e,
type: 'cxttap',
position: { x: pos[0], y: pos[1] }
};
if (down) {
down.emit(cxtTap);
} else {
cy.emit(cxtTap);
}
}
r.hoverData.cxtDragged = false;
r.hoverData.which = null;
} else if (r.hoverData.which === 1) {
// Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something
if (down == null && // not mousedown on node
!r.dragData.didDrag // didn't move the node around
&& !r.hoverData.selecting // not box selection
&& !r.hoverData.dragged // didn't pan
&& !isMultSelKeyDown(e)) {
cy.$(function (ele) {
return ele.selected();
}).unselect();
if (draggedElements.length > 0) {
r.redrawHint('eles', true);
}
r.dragData.possibleDragElements = draggedElements = [];
}
triggerEvents(near, ['mouseup', 'tapend', 'vmouseup'], e, {
position: { x: pos[0], y: pos[1] }
});
if (!r.dragData.didDrag // didn't move a node around
&& !r.hoverData.dragged // didn't pan
&& !r.hoverData.selecting // not box selection
&& !r.hoverData.isOverThresholdDrag // didn't move too much
) {
triggerEvents(down, ['click', 'tap', 'vclick'], e, {
position: { x: pos[0], y: pos[1] }
});
}
// Single selection
if (near == down && !r.dragData.didDrag && !r.hoverData.selecting) {
if (near != null && near._private.selectable) {
if (r.hoverData.dragging) {
// if panning, don't change selection state
} else if (cy.selectionType() === 'additive' || multSelKeyDown) {
if (near.selected()) {
near.unselect();
} else {
near.select();
}
} else {
if (!multSelKeyDown) {
cy.$(':selected').unmerge(near).unselect();
near.select();
}
}
r.redrawHint('eles', true);
}
}
if (r.hoverData.selecting) {
var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3]));
r.redrawHint('select', true);
if (box.length > 0) {
r.redrawHint('eles', true);
}
cy.emit('boxend');
var eleWouldBeSelected = function eleWouldBeSelected(ele) {
return ele.selectable() && !ele.selected();
};
if (cy.selectionType() === 'additive') {
box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');
} else {
if (!multSelKeyDown) {
cy.$(':selected').unmerge(box).unselect();
}
box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');
}
// always need redraw in case eles unselectable
r.redraw();
}
// Cancel drag pan
if (r.hoverData.dragging) {
r.hoverData.dragging = false;
r.redrawHint('select', true);
r.redrawHint('eles', true);
r.redraw();
}
if (!select[4]) {
r.redrawHint('drag', true);
r.redrawHint('eles', true);
var downWasGrabbed = down && down.grabbed();
freeDraggedElements(draggedElements);
if (downWasGrabbed) {
down.emit('free');
}
}
} // else not right mouse
select[4] = 0;r.hoverData.down = null;
r.hoverData.cxtStarted = false;
r.hoverData.draggingEles = false;
r.hoverData.selecting = false;
r.hoverData.isOverThresholdDrag = false;
r.dragData.didDrag = false;
r.hoverData.dragged = false;
r.hoverData.dragDelta = [];
r.hoverData.mdownPos = null;
r.hoverData.mdownGPos = null;
}, false);
var wheelHandler = function wheelHandler(e) {
if (r.scrollingPage) {
return;
} // while scrolling, ignore wheel-to-zoom
var cy = r.cy;
var pos = r.projectIntoViewport(e.clientX, e.clientY);
var rpos = [pos[0] * cy.zoom() + cy.pan().x, pos[1] * cy.zoom() + cy.pan().y];
if (r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection()) {
// if pan dragging or cxt dragging, wheel movements make no zoom
e.preventDefault();
return;
}
if (cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled()) {
e.preventDefault();
r.data.wheelZooming = true;
clearTimeout(r.data.wheelTimeout);
r.data.wheelTimeout = setTimeout(function () {
r.data.wheelZooming = false;
r.redrawHint('eles', true);
r.redraw();
}, 150);
var diff;
if (e.deltaY != null) {
diff = e.deltaY / -250;
} else if (e.wheelDeltaY != null) {
diff = e.wheelDeltaY / 1000;
} else {
diff = e.wheelDelta / 1000;
}
diff = diff * r.wheelSensitivity;
var needsWheelFix = e.deltaMode === 1;
if (needsWheelFix) {
// fixes slow wheel events on ff/linux and ff/windows
diff *= 33;
}
cy.zoom({
level: cy.zoom() * Math.pow(10, diff),
renderedPosition: { x: rpos[0], y: rpos[1] }
});
}
};
// Functions to help with whether mouse wheel should trigger zooming
// --
r.registerBinding(r.container, 'wheel', wheelHandler, true);
// disable nonstandard wheel events
// r.registerBinding(r.container, 'mousewheel', wheelHandler, true);
// r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);
// r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox
r.registerBinding(window, 'scroll', function scrollHandler(e) {
// eslint-disable-line no-undef
r.scrollingPage = true;
clearTimeout(r.scrollingPageTimeout);
r.scrollingPageTimeout = setTimeout(function () {
r.scrollingPage = false;
}, 250);
}, true);
// Functions to help with handling mouseout/mouseover on the Cytoscape container
// Handle mouseout on Cytoscape container
r.registerBinding(r.container, 'mouseout', function mouseOutHandler(e) {
var pos = r.projectIntoViewport(e.clientX, e.clientY);
r.cy.emit({
originalEvent: e,
type: 'mouseout',
position: { x: pos[0], y: pos[1] }
});
}, false);
r.registerBinding(r.container, 'mouseover', function mouseOverHandler(e) {
var pos = r.projectIntoViewport(e.clientX, e.clientY);
r.cy.emit({
originalEvent: e,
type: 'mouseover',
position: { x: pos[0], y: pos[1] }
});
}, false);
var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom
var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom
var center1, modelCenter1; // center point on start pinch to zoom
var offsetLeft, offsetTop;
var containerWidth, containerHeight;
var twoFingersStartInside;
var distance = function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
};
var distanceSq = function distanceSq(x1, y1, x2, y2) {
return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
};
var touchstartHandler;
r.registerBinding(r.container, 'touchstart', touchstartHandler = function touchstartHandler(e) {
if (!eventInContainer(e)) {
return;
}
blurActiveDomElement();
r.touchData.capture = true;
r.data.bgActivePosistion = undefined;
var cy = r.cy;
var now = r.touchData.now;
var earlier = r.touchData.earlier;
if (e.touches[0]) {
var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1];
}
if (e.touches[1]) {
var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1];
}
if (e.touches[2]) {
var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1];
}
// record starting points for pinch-to-zoom
if (e.touches[1]) {
freeDraggedElements(r.dragData.touchDragEles);
var offsets = r.findContainerClientCoords();
offsetLeft = offsets[0];
offsetTop = offsets[1];
containerWidth = offsets[2];
containerHeight = offsets[3];
f1x1 = e.touches[0].clientX - offsetLeft;
f1y1 = e.touches[0].clientY - offsetTop;
f2x1 = e.touches[1].clientX - offsetLeft;
f2y1 = e.touches[1].clientY - offsetTop;
twoFingersStartInside = 0 <= f1x1 && f1x1 <= containerWidth && 0 <= f2x1 && f2x1 <= containerWidth && 0 <= f1y1 && f1y1 <= containerHeight && 0 <= f2y1 && f2y1 <= containerHeight;
var pan = cy.pan();
var zoom = cy.zoom();
distance1 = distance(f1x1, f1y1, f2x1, f2y1);
distance1Sq = distanceSq(f1x1, f1y1, f2x1, f2y1);
center1 = [(f1x1 + f2x1) / 2, (f1y1 + f2y1) / 2];
modelCenter1 = [(center1[0] - pan.x) / zoom, (center1[1] - pan.y) / zoom];
// consider context tap
var cxtDistThreshold = 200;
var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;
if (distance1Sq < cxtDistThresholdSq && !e.touches[2]) {
var near1 = r.findNearestElement(now[0], now[1], true, true);
var near2 = r.findNearestElement(now[2], now[3], true, true);
if (near1 && near1.isNode()) {
near1.activate().emit({
originalEvent: e,
type: 'cxttapstart',
position: { x: now[0], y: now[1] }
});
r.touchData.start = near1;
} else if (near2 && near2.isNode()) {
near2.activate().emit({
originalEvent: e,
type: 'cxttapstart',
position: { x: now[0], y: now[1] }
});
r.touchData.start = near2;
} else {
cy.emit({
originalEvent: e,
type: 'cxttapstart',
position: { x: now[0], y: now[1] }
});
}
if (r.touchData.start) {
r.touchData.start._private.grabbed = false;
}
r.touchData.cxt = true;
r.touchData.cxtDragged = false;
r.data.bgActivePosistion = undefined;
r.redraw();
return;
}
}
if (e.touches[2]) {
// ignore
} else if (e.touches[1]) {
// ignore
} else if (e.touches[0]) {
var nears = r.findNearestElements(now[0], now[1], true, true);
var near = nears[0];
if (near != null) {
near.activate();
r.touchData.start = near;
r.touchData.starts = nears;
if (r.nodeIsGrabbable(near)) {
var draggedEles = r.dragData.touchDragEles = [];
var selectedNodes = null;
r.redrawHint('eles', true);
r.redrawHint('drag', true);
if (near.selected()) {
// reset drag elements, since near will be added again
selectedNodes = cy.$(function (ele) {
return ele.selected() && r.nodeIsGrabbable(ele);
});
addNodesToDrag(selectedNodes, { addToList: draggedEles });
} else {
addNodeToDrag(near, { addToList: draggedEles });
}
setGrabTarget(near);
var makeEvent = function makeEvent(type) {
return {
originalEvent: e,
type: type,
position: { x: now[0], y: now[1] }
};
};
near.emit(makeEvent('grabon'));
if (selectedNodes) {
selectedNodes.forEach(function (n) {
n.emit(makeEvent('grab'));
});
} else {
near.emit(makeEvent('grab'));
}
}
}
triggerEvents(near, ['touchstart', 'tapstart', 'vmousedown'], e, {
position: { x: now[0], y: now[1] }
});
if (near == null) {
r.data.bgActivePosistion = {
x: pos[0],
y: pos[1]
};
r.redrawHint('select', true);
r.redraw();
}
// Tap, taphold
// -----
r.touchData.singleTouchMoved = false;
r.touchData.singleTouchStartTime = +new Date();
clearTimeout(r.touchData.tapholdTimeout);
r.touchData.tapholdTimeout = setTimeout(function () {
if (r.touchData.singleTouchMoved === false && !r.pinching // if pinching, then taphold unselect shouldn't take effect
&& !r.touchData.selecting // box selection shouldn't allow taphold through
) {
triggerEvents(r.touchData.start, ['taphold'], e, {
position: { x: now[0], y: now[1] }
});
if (!r.touchData.start) {
cy.$(':selected').unselect();
}
}
}, r.tapholdDuration);
}
if (e.touches.length >= 1) {
var sPos = r.touchData.startPosition = [];
for (var i = 0; i < now.length; i++) {
sPos[i] = earlier[i] = now[i];
}
var touch0 = e.touches[0];
r.touchData.startGPosition = [touch0.clientX, touch0.clientY];
}
}, false);
var touchmoveHandler;
r.registerBinding(window, 'touchmove', touchmoveHandler = function touchmoveHandler(e) {
// eslint-disable-line no-undef
var capture = r.touchData.capture;
if (!capture && !eventInContainer(e)) {
return;
}
var select = r.selection;
var cy = r.cy;
var now = r.touchData.now;
var earlier = r.touchData.earlier;
var zoom = cy.zoom();
if (e.touches[0]) {
var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1];
}
if (e.touches[1]) {
var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1];
}
if (e.touches[2]) {
var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1];
}
var startGPos = r.touchData.startGPosition;
var isOverThresholdDrag;
if (capture && e.touches[0] && startGPos) {
var disp = [];for (var j = 0; j < now.length; j++) {
disp[j] = now[j] - earlier[j];
}
var dx = e.touches[0].clientX - startGPos[0];
var dx2 = dx * dx;
var dy = e.touches[0].clientY - startGPos[1];
var dy2 = dy * dy;
var dist2 = dx2 + dy2;
isOverThresholdDrag = dist2 >= r.touchTapThreshold2;
}
// context swipe cancelling
if (capture && r.touchData.cxt) {
e.preventDefault();
var f1x2 = e.touches[0].clientX - offsetLeft,
f1y2 = e.touches[0].clientY - offsetTop;
var f2x2 = e.touches[1].clientX - offsetLeft,
f2y2 = e.touches[1].clientY - offsetTop;
// var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );
var distance2Sq = distanceSq(f1x2, f1y2, f2x2, f2y2);
var factorSq = distance2Sq / distance1Sq;
var distThreshold = 150;
var distThresholdSq = distThreshold * distThreshold;
var factorThreshold = 1.5;
var factorThresholdSq = factorThreshold * factorThreshold;
// cancel ctx gestures if the distance b/t the fingers increases
if (factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq) {
r.touchData.cxt = false;
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
var cxtEvt = {
originalEvent: e,
type: 'cxttapend',
position: { x: now[0], y: now[1] }
};
if (r.touchData.start) {
r.touchData.start.unactivate().emit(cxtEvt);
r.touchData.start = null;
} else {
cy.emit(cxtEvt);
}
}
}
// context swipe
if (capture && r.touchData.cxt) {
var cxtEvt = {
originalEvent: e,
type: 'cxtdrag',
position: { x: now[0], y: now[1] }
};
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
if (r.touchData.start) {
r.touchData.start.emit(cxtEvt);
} else {
cy.emit(cxtEvt);
}
if (r.touchData.start) {
r.touchData.start._private.grabbed = false;
}
r.touchData.cxtDragged = true;
var near = r.findNearestElement(now[0], now[1], true, true);
if (!r.touchData.cxtOver || near !== r.touchData.cxtOver) {
if (r.touchData.cxtOver) {
r.touchData.cxtOver.emit({
originalEvent: e,
type: 'cxtdragout',
position: { x: now[0], y: now[1] }
});
}
r.touchData.cxtOver = near;
if (near) {
near.emit({
originalEvent: e,
type: 'cxtdragover',
position: { x: now[0], y: now[1] }
});
}
}
// box selection
} else if (capture && e.touches[2] && cy.boxSelectionEnabled()) {
e.preventDefault();
r.data.bgActivePosistion = undefined;
this.lastThreeTouch = +new Date();
if (!r.touchData.selecting) {
cy.emit('boxstart');
}
r.touchData.selecting = true;
r.redrawHint('select', true);
if (!select || select.length === 0 || select[0] === undefined) {
select[0] = (now[0] + now[2] + now[4]) / 3;
select[1] = (now[1] + now[3] + now[5]) / 3;
select[2] = (now[0] + now[2] + now[4]) / 3 + 1;
select[3] = (now[1] + now[3] + now[5]) / 3 + 1;
} else {
select[2] = (now[0] + now[2] + now[4]) / 3;
select[3] = (now[1] + now[3] + now[5]) / 3;
}
select[4] = 1;
r.touchData.selecting = true;
r.redraw();
// pinch to zoom
} else if (capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled()) {
// two fingers => pinch to zoom
e.preventDefault();
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
var draggedEles = r.dragData.touchDragEles;
if (draggedEles) {
r.redrawHint('drag', true);
for (var i = 0; i < draggedEles.length; i++) {
var de_p = draggedEles[i]._private;
de_p.grabbed = false;
de_p.rscratch.inDragLayer = false;
}
}
// (x2, y2) for fingers 1 and 2
var f1x2 = e.touches[0].clientX - offsetLeft,
f1y2 = e.touches[0].clientY - offsetTop;
var f2x2 = e.touches[1].clientX - offsetLeft,
f2y2 = e.touches[1].clientY - offsetTop;
var distance2 = distance(f1x2, f1y2, f2x2, f2y2);
// var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );
// var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );
var factor = distance2 / distance1;
if (twoFingersStartInside) {
// delta finger1
var df1x = f1x2 - f1x1;
var df1y = f1y2 - f1y1;
// delta finger 2
var df2x = f2x2 - f2x1;
var df2y = f2y2 - f2y1;
// translation is the normalised vector of the two fingers movement
// i.e. so pinching cancels out and moving together pans
var tx = (df1x + df2x) / 2;
var ty = (df1y + df2y) / 2;
// adjust factor by the speed multiplier
// var speed = 1.5;
// if( factor > 1 ){
// factor = (factor - 1) * speed + 1;
// } else {
// factor = 1 - (1 - factor) * speed;
// }
// now calculate the zoom
var zoom1 = cy.zoom();
var zoom2 = zoom1 * factor;
var pan1 = cy.pan();
// the model center point converted to the current rendered pos
var ctrx = modelCenter1[0] * zoom1 + pan1.x;
var ctry = modelCenter1[1] * zoom1 + pan1.y;
var pan2 = {
x: -zoom2 / zoom1 * (ctrx - pan1.x - tx) + ctrx,
y: -zoom2 / zoom1 * (ctry - pan1.y - ty) + ctry
};
// remove dragged eles
if (r.touchData.start && r.touchData.start.active()) {
var draggedEles = r.dragData.touchDragEles;
freeDraggedElements(draggedEles);
r.redrawHint('drag', true);
r.redrawHint('eles', true);
r.touchData.start.unactivate().emit('free');
}
cy.viewport({
zoom: zoom2,
pan: pan2,
cancelOnFailedZoom: true
});
distance1 = distance2;
f1x1 = f1x2;
f1y1 = f1y2;
f2x1 = f2x2;
f2y1 = f2y2;
r.pinching = true;
}
// Re-project
if (e.touches[0]) {
var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1];
}
if (e.touches[1]) {
var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1];
}
if (e.touches[2]) {
var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1];
}
} else if (e.touches[0]) {
var start = r.touchData.start;
var last = r.touchData.last;
var near;
if (!r.hoverData.draggingEles && !r.swipePanning) {
near = r.findNearestElement(now[0], now[1], true, true);
}
if (capture && start != null) {
e.preventDefault();
}
// dragging nodes
if (capture && start != null && r.nodeIsDraggable(start)) {
if (isOverThresholdDrag) {
// then dragging can happen
var draggedEles = r.dragData.touchDragEles;
var justStartedDrag = !r.dragData.didDrag;
if (justStartedDrag) {
addNodesToDrag(cy.collection(draggedEles), { inDragLayer: true });
}
for (var k = 0; k < draggedEles.length; k++) {
var draggedEle = draggedEles[k];
if (r.nodeIsDraggable(draggedEle) && draggedEle.grabbed()) {
r.dragData.didDrag = true;
var dPos = draggedEle.position();
if (is.number(disp[0]) && is.number(disp[1])) {
dPos.x += disp[0];
dPos.y += disp[1];
}
if (justStartedDrag) {
r.redrawHint('eles', true);
var dragDelta = r.touchData.dragDelta;
if (dragDelta && is.number(dragDelta[0]) && is.number(dragDelta[1])) {
dPos.x += dragDelta[0];
dPos.y += dragDelta[1];
}
}
}
}
var tcol = cy.collection(draggedEles);
tcol.dirtyCompoundBoundsCache();
tcol.emit('position drag');
r.hoverData.draggingEles = true;
r.redrawHint('drag', true);
if (r.touchData.startPosition[0] == earlier[0] && r.touchData.startPosition[1] == earlier[1]) {
r.redrawHint('eles', true);
}
r.redraw();
} else {
// otherise keep track of drag delta for later
var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];
if (dragDelta.length === 0) {
dragDelta.push(disp[0]);
dragDelta.push(disp[1]);
} else {
dragDelta[0] += disp[0];
dragDelta[1] += disp[1];
}
}
}
// touchmove
{
triggerEvents(start || near, ['touchmove', 'tapdrag', 'vmousemove'], e, {
position: { x: now[0], y: now[1] }
});
if ((!start || !start.grabbed()) && near != last) {
if (last) {
last.emit({ originalEvent: e, type: 'tapdragout', position: { x: now[0], y: now[1] } });
}
if (near) {
near.emit({ originalEvent: e, type: 'tapdragover', position: { x: now[0], y: now[1] } });
}
}
r.touchData.last = near;
}
// check to cancel taphold
if (capture) {
for (var i = 0; i < now.length; i++) {
if (now[i] && r.touchData.startPosition[i] && isOverThresholdDrag) {
r.touchData.singleTouchMoved = true;
}
}
}
// panning
if (capture && (start == null || start.isEdge()) && cy.panningEnabled() && cy.userPanningEnabled()) {
var allowPassthrough = allowPanningPassthrough(start, r.touchData.starts);
if (allowPassthrough) {
e.preventDefault();
if (r.swipePanning) {
cy.panBy({
x: disp[0] * zoom,
y: disp[1] * zoom
});
} else if (isOverThresholdDrag) {
r.swipePanning = true;
cy.panBy({
x: dx * zoom,
y: dy * zoom
});
if (start) {
start.unactivate();
if (!r.data.bgActivePosistion) {
r.data.bgActivePosistion = math.array2point(r.touchData.startPosition);
}
r.redrawHint('select', true);
r.touchData.start = null;
}
}
}
// Re-project
var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);
now[0] = pos[0];now[1] = pos[1];
}
}
for (var j = 0; j < now.length; j++) {
earlier[j] = now[j];
}
//r.redraw();
// the active bg indicator should be removed when making a swipe that is neither for dragging nodes or panning
if (capture && e.touches.length > 0 && !r.hoverData.draggingEles && !r.swipePanning && r.data.bgActivePosistion != null) {
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
r.redraw();
}
}, false);
var touchcancelHandler;
r.registerBinding(window, 'touchcancel', touchcancelHandler = function touchcancelHandler(e) {
// eslint-disable-line no-undef
var start = r.touchData.start;
r.touchData.capture = false;
if (start) {
start.unactivate();
}
});
var touchendHandler;
r.registerBinding(window, 'touchend', touchendHandler = function touchendHandler(e) {
// eslint-disable-line no-undef
var start = r.touchData.start;
var capture = r.touchData.capture;
if (capture) {
if (e.touches.length === 0) {
r.touchData.capture = false;
}
e.preventDefault();
} else {
return;
}
var select = r.selection;
r.swipePanning = false;
r.hoverData.draggingEles = false;
var cy = r.cy;
var zoom = cy.zoom();
var now = r.touchData.now;
var earlier = r.touchData.earlier;
if (e.touches[0]) {
var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);now[0] = pos[0];now[1] = pos[1];
}
if (e.touches[1]) {
var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY);now[2] = pos[0];now[3] = pos[1];
}
if (e.touches[2]) {
var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY);now[4] = pos[0];now[5] = pos[1];
}
if (start) {
start.unactivate();
}
var ctxTapend;
if (r.touchData.cxt) {
ctxTapend = {
originalEvent: e,
type: 'cxttapend',
position: { x: now[0], y: now[1] }
};
if (start) {
start.emit(ctxTapend);
} else {
cy.emit(ctxTapend);
}
if (!r.touchData.cxtDragged) {
var ctxTap = {
originalEvent: e,
type: 'cxttap',
position: { x: now[0], y: now[1] }
};
if (start) {
start.emit(ctxTap);
} else {
cy.emit(ctxTap);
}
}
if (r.touchData.start) {
r.touchData.start._private.grabbed = false;
}
r.touchData.cxt = false;
r.touchData.start = null;
r.redraw();
return;
}
// no more box selection if we don't have three fingers
if (!e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting) {
r.touchData.selecting = false;
var box = cy.collection(r.getAllInBox(select[0], select[1], select[2], select[3]));
select[0] = undefined;
select[1] = undefined;
select[2] = undefined;
select[3] = undefined;
select[4] = 0;
r.redrawHint('select', true);
cy.emit('boxend');
var eleWouldBeSelected = function eleWouldBeSelected(ele) {
return ele.selectable() && !ele.selected();
};
box.emit('box').stdFilter(eleWouldBeSelected).select().emit('boxselect');
if (box.nonempty()) {
r.redrawHint('eles', true);
}
r.redraw();
}
if (start != null) {
start.unactivate();
}
if (e.touches[2]) {
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
} else if (e.touches[1]) {
// ignore
} else if (e.touches[0]) {
// ignore
// Last touch released
} else if (!e.touches[0]) {
r.data.bgActivePosistion = undefined;
r.redrawHint('select', true);
var draggedEles = r.dragData.touchDragEles;
if (start != null) {
var startWasGrabbed = start._private.grabbed;
freeDraggedElements(draggedEles);
r.redrawHint('drag', true);
r.redrawHint('eles', true);
if (startWasGrabbed) {
start.emit('free');
}
triggerEvents(start, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, {
position: { x: now[0], y: now[1] }
});
start.unactivate();
r.touchData.start = null;
} else {
var near = r.findNearestElement(now[0], now[1], true, true);
triggerEvents(near, ['touchend', 'tapend', 'vmouseup', 'tapdragout'], e, {
position: { x: now[0], y: now[1] }
});
}
var dx = r.touchData.startPosition[0] - now[0];
var dx2 = dx * dx;
var dy = r.touchData.startPosition[1] - now[1];
var dy2 = dy * dy;
var dist2 = dx2 + dy2;
var rdist2 = dist2 * zoom * zoom;
// Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance
if (start != null && !r.dragData.didDrag // didn't drag nodes around
&& start._private.selectable && rdist2 < r.touchTapThreshold2 && !r.pinching // pinch to zoom should not affect selection
) {
if (cy.selectionType() === 'single') {
cy.$(':selected').unmerge(start).unselect();
start.select();
} else {
if (start.selected()) {
start.unselect();
} else {
start.select();
}
}
r.redrawHint('eles', true);
}
// Tap event, roughly same as mouse click event for touch
if (!r.touchData.singleTouchMoved) {
triggerEvents(start, ['tap', 'vclick'], e, {
position: { x: now[0], y: now[1] }
});
}
r.touchData.singleTouchMoved = true;
}
for (var j = 0; j < now.length; j++) {
earlier[j] = now[j];
}
r.dragData.didDrag = false; // reset for next mousedown
if (e.touches.length === 0) {
r.touchData.dragDelta = [];
r.touchData.startPosition = null;
r.touchData.startGPosition = null;
}
if (e.touches.length < 2) {
r.pinching = false;
r.redrawHint('eles', true);
r.redraw();
}
//r.redraw();
}, false);
// fallback compatibility layer for ms pointer events
if (typeof TouchEvent === 'undefined') {
var pointers = [];
var makeTouch = function makeTouch(e) {
return {
clientX: e.clientX,
clientY: e.clientY,
force: 1,
identifier: e.pointerId,
pageX: e.pageX,
pageY: e.pageY,
radiusX: e.width / 2,
radiusY: e.height / 2,
screenX: e.screenX,
screenY: e.screenY,
target: e.target
};
};
var makePointer = function makePointer(e) {
return {
event: e,
touch: makeTouch(e)
};
};
var addPointer = function addPointer(e) {
pointers.push(makePointer(e));
};
var removePointer = function removePointer(e) {
for (var i = 0; i < pointers.length; i++) {
var p = pointers[i];
if (p.event.pointerId === e.pointerId) {
pointers.splice(i, 1);
return;
}
}
};
var updatePointer = function updatePointer(e) {
var p = pointers.filter(function (p) {
return p.event.pointerId === e.pointerId;
})[0];
p.event = e;
p.touch = makeTouch(e);
};
var addTouchesToEvent = function addTouchesToEvent(e) {
e.touches = pointers.map(function (p) {
return p.touch;
});
};
var pointerIsMouse = function pointerIsMouse(e) {
return e.pointerType === 'mouse' || e.pointerType === 4;
};
r.registerBinding(r.container, 'pointerdown', function (e) {
if (pointerIsMouse(e)) {
return;
} // mouse already handled
e.preventDefault();
addPointer(e);
addTouchesToEvent(e);
touchstartHandler(e);
});
r.registerBinding(r.container, 'pointerup', function (e) {
if (pointerIsMouse(e)) {
return;
} // mouse already handled
removePointer(e);
addTouchesToEvent(e);
touchendHandler(e);
});
r.registerBinding(r.container, 'pointercancel', function (e) {
if (pointerIsMouse(e)) {
return;
} // mouse already handled
removePointer(e);
addTouchesToEvent(e);
touchcancelHandler(e);
});
r.registerBinding(r.container, 'pointermove', function (e) {
if (pointerIsMouse(e)) {
return;
} // mouse already handled
e.preventDefault();
updatePointer(e);
addTouchesToEvent(e);
touchmoveHandler(e);
});
}
};
module.exports = BRp;
/***/ }),
/* 122 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var BRp = {};
BRp.generatePolygon = function (name, points) {
return this.nodeShapes[name] = {
renderer: this,
name: name,
points: points,
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl('polygon', context, centerX, centerY, width, height, this.points);
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
return math.polygonIntersectLine(x, y, this.points, nodeX, nodeY, width / 2, height / 2, padding);
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
return math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height, [0, -1], padding);
}
};
};
BRp.generateEllipse = function () {
return this.nodeShapes['ellipse'] = {
renderer: this,
name: 'ellipse',
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
return math.intersectLineEllipse(x, y, nodeX, nodeY, width / 2 + padding, height / 2 + padding);
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
return math.checkInEllipse(x, y, width, height, centerX, centerY, padding);
}
};
};
BRp.generateRoundRectangle = function () {
return this.nodeShapes['roundrectangle'] = {
renderer: this,
name: 'roundrectangle',
points: math.generateUnitNgonPointsFitToSquare(4, 0),
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
return math.roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding);
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
var cornerRadius = math.getRoundRectangleRadius(width, height);
var diam = cornerRadius * 2;
// Check hBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) {
return true;
}
// Check vBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) {
return true;
}
// Check top left quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY - height / 2 + cornerRadius, padding)) {
return true;
}
// Check top right quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY - height / 2 + cornerRadius, padding)) {
return true;
}
// Check bottom right quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) {
return true;
}
// Check bottom left quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) {
return true;
}
return false;
}
};
};
BRp.generateCutRectangle = function () {
return this.nodeShapes['cutrectangle'] = {
renderer: this,
name: 'cutrectangle',
cornerLength: math.getCutRectangleCornerLength(),
points: math.generateUnitNgonPointsFitToSquare(4, 0),
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);
},
generateCutTrianglePts: function generateCutTrianglePts(width, height, centerX, centerY) {
var cl = this.cornerLength;
var hh = height / 2;
var hw = width / 2;
var xBegin = centerX - hw;
var xEnd = centerX + hw;
var yBegin = centerY - hh;
var yEnd = centerY + hh;
// points are in clockwise order, inner (imaginary) triangle pt on [4, 5]
return {
topLeft: [xBegin, yBegin + cl, xBegin + cl, yBegin, xBegin + cl, yBegin + cl],
topRight: [xEnd - cl, yBegin, xEnd, yBegin + cl, xEnd - cl, yBegin + cl],
bottomRight: [xEnd, yEnd - cl, xEnd - cl, yEnd, xEnd - cl, yEnd - cl],
bottomLeft: [xBegin + cl, yEnd, xBegin, yEnd - cl, xBegin + cl, yEnd - cl]
};
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
var cPts = this.generateCutTrianglePts(width + 2 * padding, height + 2 * padding, nodeX, nodeY);
var pts = [].concat.apply([], [cPts.topLeft.splice(0, 4), cPts.topRight.splice(0, 4), cPts.bottomRight.splice(0, 4), cPts.bottomLeft.splice(0, 4)]);
return math.polygonIntersectLine(x, y, pts, nodeX, nodeY);
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
// Check hBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * this.cornerLength, [0, -1], padding)) {
return true;
}
// Check vBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * this.cornerLength, height, [0, -1], padding)) {
return true;
}
var cutTrianglePts = this.generateCutTrianglePts(width, height, centerX, centerY);
return math.pointInsidePolygonPoints(x, y, cutTrianglePts.topLeft) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.topRight) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.bottomRight) || math.pointInsidePolygonPoints(x, y, cutTrianglePts.bottomLeft);
}
};
};
BRp.generateBarrel = function () {
return this.nodeShapes['barrel'] = {
renderer: this,
name: 'barrel',
points: math.generateUnitNgonPointsFitToSquare(4, 0),
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
// use two fixed t values for the bezier curve approximation
var t0 = 0.15;
var t1 = 0.5;
var t2 = 0.85;
var bPts = this.generateBarrelBezierPts(width + 2 * padding, height + 2 * padding, nodeX, nodeY);
var approximateBarrelCurvePts = function approximateBarrelCurvePts(pts) {
// approximate curve pts based on the two t values
var m0 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t0);
var m1 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t1);
var m2 = math.qbezierPtAt({ x: pts[0], y: pts[1] }, { x: pts[2], y: pts[3] }, { x: pts[4], y: pts[5] }, t2);
return [pts[0], pts[1], m0.x, m0.y, m1.x, m1.y, m2.x, m2.y, pts[4], pts[5]];
};
var pts = [].concat(approximateBarrelCurvePts(bPts.topLeft), approximateBarrelCurvePts(bPts.topRight), approximateBarrelCurvePts(bPts.bottomRight), approximateBarrelCurvePts(bPts.bottomLeft));
return math.polygonIntersectLine(x, y, pts, nodeX, nodeY);
},
generateBarrelBezierPts: function generateBarrelBezierPts(width, height, centerX, centerY) {
var hh = height / 2;
var hw = width / 2;
var xBegin = centerX - hw;
var xEnd = centerX + hw;
var yBegin = centerY - hh;
var yEnd = centerY + hh;
var curveConstants = math.getBarrelCurveConstants(width, height);
var hOffset = curveConstants.heightOffset;
var wOffset = curveConstants.widthOffset;
var ctrlPtXOffset = curveConstants.ctrlPtOffsetPct * width;
// points are in clockwise order, inner (imaginary) control pt on [4, 5]
var pts = {
topLeft: [xBegin, yBegin + hOffset, xBegin + ctrlPtXOffset, yBegin, xBegin + wOffset, yBegin],
topRight: [xEnd - wOffset, yBegin, xEnd - ctrlPtXOffset, yBegin, xEnd, yBegin + hOffset],
bottomRight: [xEnd, yEnd - hOffset, xEnd - ctrlPtXOffset, yEnd, xEnd - wOffset, yEnd],
bottomLeft: [xBegin + wOffset, yEnd, xBegin + ctrlPtXOffset, yEnd, xBegin, yEnd - hOffset]
};
pts.topLeft.isTop = true;
pts.topRight.isTop = true;
pts.bottomLeft.isBottom = true;
pts.bottomRight.isBottom = true;
return pts;
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
var curveConstants = math.getBarrelCurveConstants(width, height);
var hOffset = curveConstants.heightOffset;
var wOffset = curveConstants.widthOffset;
// Check hBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - 2 * hOffset, [0, -1], padding)) {
return true;
}
// Check vBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - 2 * wOffset, height, [0, -1], padding)) {
return true;
}
var barrelCurvePts = this.generateBarrelBezierPts(width, height, centerX, centerY);
var getCurveT = function getCurveT(x, y, curvePts) {
var x0 = curvePts[4];
var x1 = curvePts[2];
var x2 = curvePts[0];
var y0 = curvePts[5];
// var y1 = curvePts[ 3 ];
var y2 = curvePts[1];
var xMin = Math.min(x0, x2);
var xMax = Math.max(x0, x2);
var yMin = Math.min(y0, y2);
var yMax = Math.max(y0, y2);
if (xMin <= x && x <= xMax && yMin <= y && y <= yMax) {
var coeff = math.bezierPtsToQuadCoeff(x0, x1, x2);
var roots = math.solveQuadratic(coeff[0], coeff[1], coeff[2], x);
var validRoots = roots.filter(function (r) {
return 0 <= r && r <= 1;
});
if (validRoots.length > 0) {
return validRoots[0];
}
}
return null;
};
var curveRegions = Object.keys(barrelCurvePts);
for (var i = 0; i < curveRegions.length; i++) {
var corner = curveRegions[i];
var cornerPts = barrelCurvePts[corner];
var t = getCurveT(x, y, cornerPts);
if (t == null) {
continue;
}
var y0 = cornerPts[5];
var y1 = cornerPts[3];
var y2 = cornerPts[1];
var bezY = math.qbezierAt(y0, y1, y2, t);
if (cornerPts.isTop && bezY <= y) {
return true;
}
if (cornerPts.isBottom && y <= bezY) {
return true;
}
}
return false;
}
};
};
BRp.generateBottomRoundrectangle = function () {
return this.nodeShapes['bottomroundrectangle'] = {
renderer: this,
name: 'bottomroundrectangle',
points: math.generateUnitNgonPointsFitToSquare(4, 0),
draw: function draw(context, centerX, centerY, width, height) {
this.renderer.nodeShapeImpl(this.name, context, centerX, centerY, width, height);
},
intersectLine: function intersectLine(nodeX, nodeY, width, height, x, y, padding) {
var topStartX = nodeX - (width / 2 + padding);
var topStartY = nodeY - (height / 2 + padding);
var topEndY = topStartY;
var topEndX = nodeX + (width / 2 + padding);
var topIntersections = math.finiteLinesIntersect(x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);
if (topIntersections.length > 0) {
return topIntersections;
}
return math.roundRectangleIntersectLine(x, y, nodeX, nodeY, width, height, padding);
},
checkPoint: function checkPoint(x, y, padding, width, height, centerX, centerY) {
var cornerRadius = math.getRoundRectangleRadius(width, height);
var diam = 2 * cornerRadius;
// Check hBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width, height - diam, [0, -1], padding)) {
return true;
}
// Check vBox
if (math.pointInsidePolygon(x, y, this.points, centerX, centerY, width - diam, height, [0, -1], padding)) {
return true;
}
// check non-rounded top side
var outerWidth = width / 2 + 2 * padding;
var outerHeight = height / 2 + 2 * padding;
var points = [centerX - outerWidth, centerY - outerHeight, centerX - outerWidth, centerY, centerX + outerWidth, centerY, centerX + outerWidth, centerY - outerHeight];
if (math.pointInsidePolygonPoints(x, y, points)) {
return true;
}
// Check bottom right quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX + width / 2 - cornerRadius, centerY + height / 2 - cornerRadius, padding)) {
return true;
}
// Check bottom left quarter circle
if (math.checkInEllipse(x, y, diam, diam, centerX - width / 2 + cornerRadius, centerY + height / 2 - cornerRadius, padding)) {
return true;
}
return false;
}
};
};
BRp.registerNodeShapes = function () {
var nodeShapes = this.nodeShapes = {};
var renderer = this;
this.generateEllipse();
this.generatePolygon('triangle', math.generateUnitNgonPointsFitToSquare(3, 0));
this.generatePolygon('rectangle', math.generateUnitNgonPointsFitToSquare(4, 0));
nodeShapes['square'] = nodeShapes['rectangle'];
this.generateRoundRectangle();
this.generateCutRectangle();
this.generateBarrel();
this.generateBottomRoundrectangle();
this.generatePolygon('diamond', [0, 1, 1, 0, 0, -1, -1, 0]);
this.generatePolygon('pentagon', math.generateUnitNgonPointsFitToSquare(5, 0));
this.generatePolygon('hexagon', math.generateUnitNgonPointsFitToSquare(6, 0));
this.generatePolygon('heptagon', math.generateUnitNgonPointsFitToSquare(7, 0));
this.generatePolygon('octagon', math.generateUnitNgonPointsFitToSquare(8, 0));
var star5Points = new Array(20);
{
var outerPoints = math.generateUnitNgonPoints(5, 0);
var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5);
// Outer radius is 1; inner radius of star is smaller
var innerRadius = 0.5 * (3 - Math.sqrt(5));
innerRadius *= 1.57;
for (var i = 0; i < innerPoints.length / 2; i++) {
innerPoints[i * 2] *= innerRadius;
innerPoints[i * 2 + 1] *= innerRadius;
}
for (var i = 0; i < 20 / 4; i++) {
star5Points[i * 4] = outerPoints[i * 2];
star5Points[i * 4 + 1] = outerPoints[i * 2 + 1];
star5Points[i * 4 + 2] = innerPoints[i * 2];
star5Points[i * 4 + 3] = innerPoints[i * 2 + 1];
}
}
star5Points = math.fitPolygonToSquare(star5Points);
this.generatePolygon('star', star5Points);
this.generatePolygon('vee', [-1, -1, 0, -0.333, 1, -1, 0, 1]);
this.generatePolygon('rhomboid', [-1, -1, 0.333, -1, 1, 1, -0.333, 1]);
this.generatePolygon('concavehexagon', [-1, -0.95, -0.75, 0, -1, 0.95, 1, 0.95, 0.75, 0, 1, -0.95]);
this.generatePolygon('tag', [-1, -1, 0.25, -1, 1, 0, 0.25, 1, -1, 1]);
nodeShapes.makePolygon = function (points) {
// use caching on user-specified polygons so they are as fast as native shapes
var key = points.join('$');
var name = 'polygon-' + key;
var shape;
if (shape = this[name]) {
// got cached shape
return shape;
}
// create and cache new shape
return renderer.generatePolygon(name, points);
};
};
module.exports = BRp;
/***/ }),
/* 123 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var BRp = {};
BRp.timeToRender = function () {
return this.redrawTotalTime / this.redrawCount;
};
BRp.redraw = function (options) {
options = options || util.staticEmptyObject();
var r = this;
if (r.averageRedrawTime === undefined) {
r.averageRedrawTime = 0;
}
if (r.lastRedrawTime === undefined) {
r.lastRedrawTime = 0;
}
if (r.lastDrawTime === undefined) {
r.lastDrawTime = 0;
}
r.requestedFrame = true;
r.renderOptions = options;
};
BRp.beforeRender = function (fn, priority) {
// the renderer can't add tick callbacks when destroyed
if (this.destroyed) {
return;
}
priority = priority || 0;
var cbs = this.beforeRenderCallbacks;
cbs.push({ fn: fn, priority: priority });
// higher priority callbacks executed first
cbs.sort(function (a, b) {
return b.priority - a.priority;
});
};
var beforeRenderCallbacks = function beforeRenderCallbacks(r, willDraw, startTime) {
var cbs = r.beforeRenderCallbacks;
for (var i = 0; i < cbs.length; i++) {
cbs[i].fn(willDraw, startTime);
}
};
BRp.startRenderLoop = function () {
var r = this;
if (r.renderLoopStarted) {
return;
} else {
r.renderLoopStarted = true;
}
var renderFn = function renderFn(requestTime) {
if (r.destroyed) {
return;
}
if (r.requestedFrame && !r.skipFrame) {
beforeRenderCallbacks(r, true, requestTime);
var startTime = util.performanceNow();
r.render(r.renderOptions);
var endTime = r.lastDrawTime = util.performanceNow();
if (r.averageRedrawTime === undefined) {
r.averageRedrawTime = endTime - startTime;
}
if (r.redrawCount === undefined) {
r.redrawCount = 0;
}
r.redrawCount++;
if (r.redrawTotalTime === undefined) {
r.redrawTotalTime = 0;
}
var duration = endTime - startTime;
r.redrawTotalTime += duration;
r.lastRedrawTime = duration;
// use a weighted average with a bias from the previous average so we don't spike so easily
r.averageRedrawTime = r.averageRedrawTime / 2 + duration / 2;
r.requestedFrame = false;
} else {
beforeRenderCallbacks(r, false, requestTime);
}
r.skipFrame = false;
util.requestAnimationFrame(renderFn);
};
util.requestAnimationFrame(renderFn);
};
module.exports = BRp;
/***/ }),
/* 124 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/*
The canvas renderer was written by Yue Dong.
Modifications tracked on Github.
*/
var util = __webpack_require__(1);
var is = __webpack_require__(0);
var ElementTextureCache = __webpack_require__(125);
var LayeredTextureCache = __webpack_require__(126);
var CR = CanvasRenderer;
var CRp = CanvasRenderer.prototype;
CRp.CANVAS_LAYERS = 3;
//
CRp.SELECT_BOX = 0;
CRp.DRAG = 1;
CRp.NODE = 2;
CRp.BUFFER_COUNT = 3;
//
CRp.TEXTURE_BUFFER = 0;
CRp.MOTIONBLUR_BUFFER_NODE = 1;
CRp.MOTIONBLUR_BUFFER_DRAG = 2;
function CanvasRenderer(options) {
var r = this;
r.data = {
canvases: new Array(CRp.CANVAS_LAYERS),
contexts: new Array(CRp.CANVAS_LAYERS),
canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS),
bufferCanvases: new Array(CRp.BUFFER_COUNT),
bufferContexts: new Array(CRp.CANVAS_LAYERS)
};
var tapHlOff = '-webkit-tap-highlight-color: rgba(0,0,0,0);';
r.data.canvasContainer = document.createElement('div'); // eslint-disable-line no-undef
var containerStyle = r.data.canvasContainer.style;
r.data.canvasContainer.setAttribute('style', tapHlOff);
containerStyle.position = 'relative';
containerStyle.zIndex = '0';
containerStyle.overflow = 'hidden';
var container = options.cy.container();
container.appendChild(r.data.canvasContainer);
if ((container.getAttribute('style') || '').indexOf(tapHlOff) < 0) {
container.setAttribute('style', (container.getAttribute('style') || '') + tapHlOff);
}
for (var i = 0; i < CRp.CANVAS_LAYERS; i++) {
var canvas = r.data.canvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef
r.data.contexts[i] = canvas.getContext('2d');
canvas.setAttribute('style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + (is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : ''));
canvas.style.position = 'absolute';
canvas.setAttribute('data-id', 'layer' + i);
canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i);
r.data.canvasContainer.appendChild(canvas);
r.data.canvasNeedsRedraw[i] = false;
}
r.data.topCanvas = r.data.canvases[0];
r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node');
r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox');
r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag');
for (var i = 0; i < CRp.BUFFER_COUNT; i++) {
r.data.bufferCanvases[i] = document.createElement('canvas'); // eslint-disable-line no-undef
r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');
r.data.bufferCanvases[i].style.position = 'absolute';
r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);
r.data.bufferCanvases[i].style.zIndex = String(-i - 1);
r.data.bufferCanvases[i].style.visibility = 'hidden';
//r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);
}
r.pathsEnabled = true;
r.data.eleTxrCache = new ElementTextureCache(r);
r.data.lyrTxrCache = new LayeredTextureCache(r, r.data.eleTxrCache);
r.onUpdateEleCalcs(function invalidateTextureCaches(willDraw, eles) {
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var rs = ele._private.rstyle;
var de = rs.dirtyEvents;
if (ele.isNode() && de && de.length === 1 && de['position']) {
// then keep cached ele texture
} else {
r.data.eleTxrCache.invalidateElement(ele);
// NB this block of code should not be ported to 3.3 (unstable branch).
// - This check is unneccesary in 3.3 as caches will be stored without respect to opacity.
// - This fix may result in lowered performance for compound graphs.
// - Ref : Opacity of child node is not updated for certain zoom levels after parent opacity is overriden #2078
if (ele.isParent() && de['style']) {
var op1 = rs.prevParentOpacity;
var op2 = ele.pstyle('opacity').pfValue;
rs.prevParentOpacity = op2;
if (op1 !== op2) {
var descs = ele.descendants();
for (var j = 0; j < descs.length; j++) {
r.data.eleTxrCache.invalidateElement(descs[j]);
}
}
}
}
}
if (eles.length > 0) {
r.data.lyrTxrCache.invalidateElements(eles);
}
});
}
CRp.redrawHint = function (group, bool) {
var r = this;
switch (group) {
case 'eles':
r.data.canvasNeedsRedraw[CRp.NODE] = bool;
break;
case 'drag':
r.data.canvasNeedsRedraw[CRp.DRAG] = bool;
break;
case 'select':
r.data.canvasNeedsRedraw[CRp.SELECT_BOX] = bool;
break;
}
};
// whether to use Path2D caching for drawing
var pathsImpld = typeof Path2D !== 'undefined';
CRp.path2dEnabled = function (on) {
if (on === undefined) {
return this.pathsEnabled;
}
this.pathsEnabled = on ? true : false;
};
CRp.usePaths = function () {
return pathsImpld && this.pathsEnabled;
};
[__webpack_require__(127), __webpack_require__(128), __webpack_require__(129), __webpack_require__(130), __webpack_require__(131), __webpack_require__(132), __webpack_require__(133), __webpack_require__(134), __webpack_require__(135), __webpack_require__(136)].forEach(function (props) {
util.extend(CRp, props);
});
module.exports = CR;
/***/ }),
/* 125 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var util = __webpack_require__(1);
var Heap = __webpack_require__(9);
var defs = __webpack_require__(19);
var minTxrH = 25; // the size of the texture cache for small height eles (special case)
var txrStepH = 50; // the min size of the regular cache, and the size it increases with each step up
var minLvl = -4; // when scaling smaller than that we don't need to re-render
var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful)
var maxZoom = 3.99; // beyond this zoom level, layered textures are not used
var eleTxrSpacing = 8; // spacing between elements on textures to avoid blitting overlaps
var defTxrWidth = 1024; // default/minimum texture width
var maxTxrW = 1024; // the maximum width of a texture
var maxTxrH = 1024; // the maximum height of a texture
var minUtility = 0.5; // if usage of texture is less than this, it is retired
var maxFullness = 0.8; // fullness of texture after which queue removal is checked
var maxFullnessChecks = 10; // dequeued after this many checks
var allowEdgeTxrCaching = false; // whether edges can be cached as textures (TODO maybe better on if webgl supported?)
var allowParentTxrCaching = false; // whether parent nodes can be cached as textures (TODO maybe better on if webgl supported?)
var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame
var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time
var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing
var deqFastCost = 0.9; // % of frame time to be used when >60fps
var deqRedrawThreshold = 100; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile
var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch
var getTxrReasons = {
dequeue: 'dequeue',
downscale: 'downscale',
highQuality: 'highQuality'
};
var ElementTextureCache = function ElementTextureCache(renderer) {
var self = this;
self.renderer = renderer;
self.onDequeues = [];
self.setupDequeueing();
};
var ETCp = ElementTextureCache.prototype;
ETCp.reasons = getTxrReasons;
// the list of textures in which new subtextures for elements can be placed
ETCp.getTextureQueue = function (txrH) {
var self = this;
self.eleImgCaches = self.eleImgCaches || {};
return self.eleImgCaches[txrH] = self.eleImgCaches[txrH] || [];
};
// the list of usused textures which can be recycled (in use in texture queue)
ETCp.getRetiredTextureQueue = function (txrH) {
var self = this;
var rtxtrQs = self.eleImgCaches.retired = self.eleImgCaches.retired || {};
var rtxtrQ = rtxtrQs[txrH] = rtxtrQs[txrH] || [];
return rtxtrQ;
};
// queue of element draw requests at different scale levels
ETCp.getElementQueue = function () {
var self = this;
var q = self.eleCacheQueue = self.eleCacheQueue || new Heap(function (a, b) {
return b.reqs - a.reqs;
});
return q;
};
// queue of element draw requests at different scale levels (element id lookup)
ETCp.getElementIdToQueue = function () {
var self = this;
var id2q = self.eleIdToCacheQueue = self.eleIdToCacheQueue || {};
return id2q;
};
ETCp.getElement = function (ele, bb, pxRatio, lvl, reason) {
var self = this;
var r = this.renderer;
var rs = ele._private.rscratch;
var zoom = r.cy.zoom();
if (bb.w === 0 || bb.h === 0 || !ele.visible()) {
return null;
}
if (lvl == null) {
lvl = Math.ceil(math.log2(zoom * pxRatio));
}
if (lvl < minLvl) {
lvl = minLvl;
} else if (zoom >= maxZoom || lvl > maxLvl) {
return null;
}
var scale = Math.pow(2, lvl);
var eleScaledH = bb.h * scale;
var eleScaledW = bb.w * scale;
var caches = rs.imgCaches = rs.imgCaches || {};
var eleCache = caches[lvl];
if (eleCache) {
return eleCache;
}
var txrH; // which texture height this ele belongs to
if (eleScaledH <= minTxrH) {
txrH = minTxrH;
} else if (eleScaledH <= txrStepH) {
txrH = txrStepH;
} else {
txrH = Math.ceil(eleScaledH / txrStepH) * txrStepH;
}
if (eleScaledH > maxTxrH || eleScaledW > maxTxrW || !allowEdgeTxrCaching && ele.isEdge() || !allowParentTxrCaching && ele.isParent()) {
return null; // caching large elements is not efficient
}
var txrQ = self.getTextureQueue(txrH);
// first try the second last one in case it has space at the end
var txr = txrQ[txrQ.length - 2];
var addNewTxr = function addNewTxr() {
return self.recycleTexture(txrH, eleScaledW) || self.addTexture(txrH, eleScaledW);
};
// try the last one if there is no second last one
if (!txr) {
txr = txrQ[txrQ.length - 1];
}
// if the last one doesn't exist, we need a first one
if (!txr) {
txr = addNewTxr();
}
// if there's no room in the current texture, we need a new one
if (txr.width - txr.usedWidth < eleScaledW) {
txr = addNewTxr();
}
var scaledLabelShown = r.eleTextBiggerThanMin(ele, scale);
var scalableFrom = function scalableFrom(otherCache) {
return otherCache && otherCache.scaledLabelShown === scaledLabelShown;
};
var deqing = reason && reason === getTxrReasons.dequeue;
var highQualityReq = reason && reason === getTxrReasons.highQuality;
var downscaleReq = reason && reason === getTxrReasons.downscale;
var higherCache; // the nearest cache with a higher level
for (var l = lvl + 1; l <= maxLvl; l++) {
var c = caches[l];
if (c) {
higherCache = c;break;
}
}
var oneUpCache = higherCache && higherCache.level === lvl + 1 ? higherCache : null;
var downscale = function downscale() {
txr.context.drawImage(oneUpCache.texture.canvas, oneUpCache.x, 0, oneUpCache.width, oneUpCache.height, txr.usedWidth, 0, eleScaledW, eleScaledH);
};
// reset ele area in texture
txr.context.setTransform(1, 0, 0, 1, 0, 0);
txr.context.clearRect(txr.usedWidth, 0, eleScaledW, txrH);
if (scalableFrom(oneUpCache)) {
// then we can relatively cheaply rescale the existing image w/o rerendering
downscale();
} else if (scalableFrom(higherCache)) {
// then use the higher cache for now and queue the next level down
// to cheaply scale towards the smaller level
if (highQualityReq) {
for (var l = higherCache.level; l > lvl; l--) {
oneUpCache = self.getElement(ele, bb, pxRatio, l, getTxrReasons.downscale);
}
downscale();
} else {
self.queueElement(ele, higherCache.level - 1);
return higherCache;
}
} else {
var lowerCache; // the nearest cache with a lower level
if (!deqing && !highQualityReq && !downscaleReq) {
for (var l = lvl - 1; l >= minLvl; l--) {
var c = caches[l];
if (c) {
lowerCache = c;break;
}
}
}
if (scalableFrom(lowerCache)) {
// then use the lower quality cache for now and queue the better one for later
self.queueElement(ele, lvl);
return lowerCache;
}
txr.context.translate(txr.usedWidth, 0);
txr.context.scale(scale, scale);
r.drawElement(txr.context, ele, bb, scaledLabelShown);
txr.context.scale(1 / scale, 1 / scale);
txr.context.translate(-txr.usedWidth, 0);
}
eleCache = caches[lvl] = {
ele: ele,
x: txr.usedWidth,
texture: txr,
level: lvl,
scale: scale,
width: eleScaledW,
height: eleScaledH,
scaledLabelShown: scaledLabelShown
};
txr.usedWidth += Math.ceil(eleScaledW + eleTxrSpacing);
txr.eleCaches.push(eleCache);
self.checkTextureFullness(txr);
return eleCache;
};
ETCp.invalidateElement = function (ele) {
var self = this;
var caches = ele._private.rscratch.imgCaches;
if (caches) {
for (var lvl = minLvl; lvl <= maxLvl; lvl++) {
var cache = caches[lvl];
if (cache) {
var txr = cache.texture;
// remove space from the texture it belongs to
txr.invalidatedWidth += cache.width;
// remove refs with the element
caches[lvl] = null;
util.removeFromArray(txr.eleCaches, cache);
// remove from queue since the old req was for the old state
self.removeFromQueue(ele);
// might have to remove the entire texture if it's not efficiently using its space
self.checkTextureUtility(txr);
}
}
}
};
ETCp.checkTextureUtility = function (txr) {
// invalidate all entries in the cache if the cache size is small
if (txr.invalidatedWidth >= minUtility * txr.width) {
this.retireTexture(txr);
}
};
ETCp.checkTextureFullness = function (txr) {
// if texture has been mostly filled and passed over several times, remove
// it from the queue so we don't need to waste time looking at it to put new things
var self = this;
var txrQ = self.getTextureQueue(txr.height);
if (txr.usedWidth / txr.width > maxFullness && txr.fullnessChecks >= maxFullnessChecks) {
util.removeFromArray(txrQ, txr);
} else {
txr.fullnessChecks++;
}
};
ETCp.retireTexture = function (txr) {
var self = this;
var txrH = txr.height;
var txrQ = self.getTextureQueue(txrH);
// retire the texture from the active / searchable queue:
util.removeFromArray(txrQ, txr);
txr.retired = true;
// remove the refs from the eles to the caches:
var eleCaches = txr.eleCaches;
for (var i = 0; i < eleCaches.length; i++) {
var eleCache = eleCaches[i];
var ele = eleCache.ele;
var lvl = eleCache.level;
var imgCaches = ele._private.rscratch.imgCaches;
if (imgCaches) {
imgCaches[lvl] = null;
}
}
util.clearArray(eleCaches);
// add the texture to a retired queue so it can be recycled in future:
var rtxtrQ = self.getRetiredTextureQueue(txrH);
rtxtrQ.push(txr);
};
ETCp.addTexture = function (txrH, minW) {
var self = this;
var txrQ = self.getTextureQueue(txrH);
var txr = {};
txrQ.push(txr);
txr.eleCaches = [];
txr.height = txrH;
txr.width = Math.max(defTxrWidth, minW);
txr.usedWidth = 0;
txr.invalidatedWidth = 0;
txr.fullnessChecks = 0;
txr.canvas = document.createElement('canvas'); // eslint-disable-line no-undef
txr.canvas.width = txr.width;
txr.canvas.height = txr.height;
txr.context = txr.canvas.getContext('2d');
return txr;
};
ETCp.recycleTexture = function (txrH, minW) {
var self = this;
var txrQ = self.getTextureQueue(txrH);
var rtxtrQ = self.getRetiredTextureQueue(txrH);
for (var i = 0; i < rtxtrQ.length; i++) {
var txr = rtxtrQ[i];
if (txr.width >= minW) {
txr.retired = false;
txr.usedWidth = 0;
txr.invalidatedWidth = 0;
txr.fullnessChecks = 0;
util.clearArray(txr.eleCaches);
txr.context.setTransform(1, 0, 0, 1, 0, 0);
txr.context.clearRect(0, 0, txr.width, txr.height);
util.removeFromArray(rtxtrQ, txr);
txrQ.push(txr);
return txr;
}
}
};
ETCp.queueElement = function (ele, lvl) {
var self = this;
var q = self.getElementQueue();
var id2q = self.getElementIdToQueue();
var id = ele.id();
var existingReq = id2q[id];
if (existingReq) {
// use the max lvl b/c in between lvls are cheap to make
existingReq.level = Math.max(existingReq.level, lvl);
existingReq.reqs++;
q.updateItem(existingReq);
} else {
var req = {
ele: ele,
level: lvl,
reqs: 1
};
q.push(req);
id2q[id] = req;
}
};
ETCp.dequeue = function (pxRatio /*, extent*/) {
var self = this;
var q = self.getElementQueue();
var id2q = self.getElementIdToQueue();
var dequeued = [];
for (var i = 0; i < maxDeqSize; i++) {
if (q.size() > 0) {
var req = q.pop();
var ele = req.ele;
var caches = ele._private.rscratch.imgCaches;
// dequeueing isn't necessary when an existing cache exists
if (caches[req.level] != null) {
continue;
}
id2q[ele.id()] = null;
dequeued.push(req);
var bb = ele.boundingBox();
self.getElement(ele, bb, pxRatio, req.level, getTxrReasons.dequeue);
} else {
break;
}
}
return dequeued;
};
ETCp.removeFromQueue = function (ele) {
var self = this;
var q = self.getElementQueue();
var id2q = self.getElementIdToQueue();
var req = id2q[ele.id()];
if (req != null) {
// bring to front of queue
req.reqs = util.MAX_INT;
q.updateItem(req);
q.pop(); // remove from queue
id2q[ele.id()] = null; // remove from lookup map
}
};
ETCp.onDequeue = function (fn) {
this.onDequeues.push(fn);
};
ETCp.offDequeue = function (fn) {
util.removeFromArray(this.onDequeues, fn);
};
ETCp.setupDequeueing = defs.setupDequeueing({
deqRedrawThreshold: deqRedrawThreshold,
deqCost: deqCost,
deqAvgCost: deqAvgCost,
deqNoDrawCost: deqNoDrawCost,
deqFastCost: deqFastCost,
deq: function deq(self, pxRatio, extent) {
return self.dequeue(pxRatio, extent);
},
onDeqd: function onDeqd(self, deqd) {
for (var i = 0; i < self.onDequeues.length; i++) {
var fn = self.onDequeues[i];
fn(deqd);
}
},
shouldRedraw: function shouldRedraw(self, deqd, pxRatio, extent) {
for (var i = 0; i < deqd.length; i++) {
var bb = deqd[i].ele.boundingBox();
if (math.boundingBoxesIntersect(bb, extent)) {
return true;
}
}
return false;
},
priority: function priority(self) {
return self.renderer.beforeRenderPriorities.eleTxrDeq;
}
});
module.exports = ElementTextureCache;
/***/ }),
/* 126 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var Heap = __webpack_require__(9);
var is = __webpack_require__(0);
var defs = __webpack_require__(19);
var defNumLayers = 1; // default number of layers to use
var minLvl = -4; // when scaling smaller than that we don't need to re-render
var maxLvl = 2; // when larger than this scale just render directly (caching is not helpful)
var maxZoom = 3.99; // beyond this zoom level, layered textures are not used
var deqRedrawThreshold = 50; // time to batch redraws together from dequeueing to allow more dequeueing calcs to happen in the meanwhile
var refineEleDebounceTime = 50; // time to debounce sharper ele texture updates
var disableEleImgSmoothing = true; // when drawing eles on layers from an ele cache ; crisper and more performant when true
var deqCost = 0.15; // % of add'l rendering cost allowed for dequeuing ele caches each frame
var deqAvgCost = 0.1; // % of add'l rendering cost compared to average overall redraw time
var deqNoDrawCost = 0.9; // % of avg frame time that can be used for dequeueing when not drawing
var deqFastCost = 0.9; // % of frame time to be used when >60fps
var maxDeqSize = 1; // number of eles to dequeue and render at higher texture in each batch
var invalidThreshold = 250; // time threshold for disabling b/c of invalidations
var maxLayerArea = 4000 * 4000; // layers can't be bigger than this
var alwaysQueue = true; // never draw all the layers in a level on a frame; draw directly until all dequeued
var useHighQualityEleTxrReqs = true; // whether to use high quality ele txr requests (generally faster and cheaper in the longterm)
var useEleTxrCaching = true; // whether to use individual ele texture caching underneath this cache
// var log = function(){ console.log.apply( console, arguments ); };
var LayeredTextureCache = function LayeredTextureCache(renderer, eleTxrCache) {
var self = this;
var r = self.renderer = renderer;
self.layersByLevel = {}; // e.g. 2 => [ layer1, layer2, ..., layerN ]
self.firstGet = true;
self.lastInvalidationTime = util.performanceNow() - 2 * invalidThreshold;
self.skipping = false;
r.beforeRender(function (willDraw, now) {
if (now - self.lastInvalidationTime <= invalidThreshold) {
self.skipping = true;
} else {
self.skipping = false;
}
});
var qSort = function qSort(a, b) {
return b.reqs - a.reqs;
};
self.layersQueue = new Heap(qSort);
self.eleTxrCache = eleTxrCache;
self.setupEleCacheInvalidation();
self.setupDequeueing();
};
var LTCp = LayeredTextureCache.prototype;
var layerIdPool = 0;
var MAX_INT = Math.pow(2, 53) - 1;
LTCp.makeLayer = function (bb, lvl) {
var scale = Math.pow(2, lvl);
var w = Math.ceil(bb.w * scale);
var h = Math.ceil(bb.h * scale);
var canvas = document.createElement('canvas'); // eslint-disable-line no-undef
canvas.width = w;
canvas.height = h;
var layer = {
id: layerIdPool = ++layerIdPool % MAX_INT,
bb: bb,
level: lvl,
width: w,
height: h,
canvas: canvas,
context: canvas.getContext('2d'),
eles: [],
elesQueue: [],
reqs: 0
};
// log('make layer %s with w %s and h %s and lvl %s', layer.id, layer.width, layer.height, layer.level);
var cxt = layer.context;
var dx = -layer.bb.x1;
var dy = -layer.bb.y1;
// do the transform on creation to save cycles (it's the same for all eles)
cxt.scale(scale, scale);
cxt.translate(dx, dy);
return layer;
};
LTCp.getLayers = function (eles, pxRatio, lvl) {
var self = this;
var r = self.renderer;
var cy = r.cy;
var zoom = cy.zoom();
var firstGet = self.firstGet;
self.firstGet = false;
// log('--\nget layers with %s eles', eles.length);
//log eles.map(function(ele){ return ele.id() }) );
if (lvl == null) {
lvl = Math.ceil(math.log2(zoom * pxRatio));
if (lvl < minLvl) {
lvl = minLvl;
} else if (zoom >= maxZoom || lvl > maxLvl) {
return null;
}
}
self.validateLayersElesOrdering(lvl, eles);
var layersByLvl = self.layersByLevel;
var scale = Math.pow(2, lvl);
var layers = layersByLvl[lvl] = layersByLvl[lvl] || [];
var bb;
var lvlComplete = self.levelIsComplete(lvl, eles);
var tmpLayers;
var checkTempLevels = function checkTempLevels() {
var canUseAsTmpLvl = function canUseAsTmpLvl(l) {
self.validateLayersElesOrdering(l, eles);
if (self.levelIsComplete(l, eles)) {
tmpLayers = layersByLvl[l];
return true;
}
};
var checkLvls = function checkLvls(dir) {
if (tmpLayers) {
return;
}
for (var l = lvl + dir; minLvl <= l && l <= maxLvl; l += dir) {
if (canUseAsTmpLvl(l)) {
break;
}
}
};
checkLvls(+1);
checkLvls(-1);
// remove the invalid layers; they will be replaced as needed later in this function
for (var i = layers.length - 1; i >= 0; i--) {
var layer = layers[i];
if (layer.invalid) {
util.removeFromArray(layers, layer);
}
}
};
if (!lvlComplete) {
// if the current level is incomplete, then use the closest, best quality layerset temporarily
// and later queue the current layerset so we can get the proper quality level soon
checkTempLevels();
} else {
// log('level complete, using existing layers\n--');
return layers;
}
var getBb = function getBb() {
if (!bb) {
bb = math.makeBoundingBox();
for (var i = 0; i < eles.length; i++) {
math.updateBoundingBox(bb, eles[i].boundingBox());
}
}
return bb;
};
var makeLayer = function makeLayer(opts) {
opts = opts || {};
var after = opts.after;
getBb();
var area = bb.w * scale * (bb.h * scale);
if (area > maxLayerArea) {
return null;
}
var layer = self.makeLayer(bb, lvl);
if (after != null) {
var index = layers.indexOf(after) + 1;
layers.splice(index, 0, layer);
} else if (opts.insert === undefined || opts.insert) {
// no after specified => first layer made so put at start
layers.unshift(layer);
}
// if( tmpLayers ){
//self.queueLayer( layer );
// }
return layer;
};
if (self.skipping && !firstGet) {
// log('skip layers');
return null;
}
// log('do layers');
var layer = null;
var maxElesPerLayer = eles.length / defNumLayers;
var allowLazyQueueing = alwaysQueue && !firstGet;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var rs = ele._private.rscratch;
var caches = rs.imgLayerCaches = rs.imgLayerCaches || {};
// log('look at ele', ele.id());
var existingLayer = caches[lvl];
if (existingLayer) {
// reuse layer for later eles
// log('reuse layer for', ele.id());
layer = existingLayer;
continue;
}
if (!layer || layer.eles.length >= maxElesPerLayer || !math.boundingBoxInBoundingBox(layer.bb, ele.boundingBox())) {
// log('make new layer for ele %s', ele.id());
layer = makeLayer({ insert: true, after: layer });
// if now layer can be built then we can't use layers at this level
if (!layer) {
return null;
}
// log('new layer with id %s', layer.id);
}
if (tmpLayers || allowLazyQueueing) {
// log('queue ele %s in layer %s', ele.id(), layer.id);
self.queueLayer(layer, ele);
} else {
// log('draw ele %s in layer %s', ele.id(), layer.id);
self.drawEleInLayer(layer, ele, lvl, pxRatio);
}
layer.eles.push(ele);
caches[lvl] = layer;
}
// log('--');
if (tmpLayers) {
// then we only queued the current layerset and can't draw it yet
return tmpLayers;
}
if (allowLazyQueueing) {
// log('lazy queue level', lvl);
return null;
}
return layers;
};
// a layer may want to use an ele cache of a higher level to avoid blurriness
// so the layer level might not equal the ele level
LTCp.getEleLevelForLayerLevel = function (lvl, pxRatio) {
return lvl;
};
function imgSmoothing(context, bool) {
if (context.imageSmoothingEnabled != null) {
context.imageSmoothingEnabled = bool;
} else {
context.webkitImageSmoothingEnabled = bool;
context.mozImageSmoothingEnabled = bool;
context.msImageSmoothingEnabled = bool;
}
}
LTCp.drawEleInLayer = function (layer, ele, lvl, pxRatio) {
var self = this;
var r = this.renderer;
var context = layer.context;
var bb = ele.boundingBox();
if (bb.w === 0 || bb.h === 0 || !ele.visible()) {
return;
}
var eleCache = self.eleTxrCache;
var reason = useHighQualityEleTxrReqs ? eleCache.reasons.highQuality : undefined;
lvl = self.getEleLevelForLayerLevel(lvl, pxRatio);
var cache = useEleTxrCaching ? eleCache.getElement(ele, bb, null, lvl, reason) : null;
if (cache) {
if (disableEleImgSmoothing) {
imgSmoothing(context, false);
}
context.drawImage(cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h);
if (disableEleImgSmoothing) {
imgSmoothing(context, true);
}
} else {
// if the element is not cacheable, then draw directly
r.drawElement(context, ele);
}
};
LTCp.levelIsComplete = function (lvl, eles) {
var self = this;
var layers = self.layersByLevel[lvl];
if (!layers || layers.length === 0) {
return false;
}
var numElesInLayers = 0;
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
// if there are any eles needed to be drawn yet, the level is not complete
if (layer.reqs > 0) {
return false;
}
// if the layer is invalid, the level is not complete
if (layer.invalid) {
return false;
}
numElesInLayers += layer.eles.length;
}
// we should have exactly the number of eles passed in to be complete
if (numElesInLayers !== eles.length) {
return false;
}
return true;
};
LTCp.validateLayersElesOrdering = function (lvl, eles) {
var layers = this.layersByLevel[lvl];
if (!layers) {
return;
}
// if in a layer the eles are not in the same order, then the layer is invalid
// (i.e. there is an ele in between the eles in the layer)
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
var offset = -1;
// find the offset
for (var j = 0; j < eles.length; j++) {
if (layer.eles[0] === eles[j]) {
offset = j;
break;
}
}
if (offset < 0) {
// then the layer has nonexistant elements and is invalid
this.invalidateLayer(layer);
continue;
}
// the eles in the layer must be in the same continuous order, else the layer is invalid
var o = offset;
for (var j = 0; j < layer.eles.length; j++) {
if (layer.eles[j] !== eles[o + j]) {
// log('invalidate based on ordering', layer.id);
this.invalidateLayer(layer);
break;
}
}
}
};
LTCp.updateElementsInLayers = function (eles, update) {
var self = this;
var isEles = is.element(eles[0]);
// collect udpated elements (cascaded from the layers) and update each
// layer itself along the way
for (var i = 0; i < eles.length; i++) {
var req = isEles ? null : eles[i];
var ele = isEles ? eles[i] : eles[i].ele;
var rs = ele._private.rscratch;
var caches = rs.imgLayerCaches = rs.imgLayerCaches || {};
for (var l = minLvl; l <= maxLvl; l++) {
var layer = caches[l];
if (!layer) {
continue;
}
// if update is a request from the ele cache, then it affects only
// the matching level
if (req && self.getEleLevelForLayerLevel(layer.level) !== req.level) {
continue;
}
update(layer, ele, req);
}
}
};
LTCp.haveLayers = function () {
var self = this;
var haveLayers = false;
for (var l = minLvl; l <= maxLvl; l++) {
var layers = self.layersByLevel[l];
if (layers && layers.length > 0) {
haveLayers = true;
break;
}
}
return haveLayers;
};
LTCp.invalidateElements = function (eles) {
var self = this;
self.lastInvalidationTime = util.performanceNow();
// log('update invalidate layer time from eles');
if (eles.length === 0 || !self.haveLayers()) {
return;
}
self.updateElementsInLayers(eles, function invalAssocLayers(layer, ele, req) {
self.invalidateLayer(layer);
});
};
LTCp.invalidateLayer = function (layer) {
// log('update invalidate layer time');
this.lastInvalidationTime = util.performanceNow();
if (layer.invalid) {
return;
} // save cycles
var lvl = layer.level;
var eles = layer.eles;
var layers = this.layersByLevel[lvl];
// log('invalidate layer', layer.id );
util.removeFromArray(layers, layer);
// layer.eles = [];
layer.elesQueue = [];
layer.invalid = true;
if (layer.replacement) {
layer.replacement.invalid = true;
}
for (var i = 0; i < eles.length; i++) {
var caches = eles[i]._private.rscratch.imgLayerCaches;
if (caches) {
caches[lvl] = null;
}
}
};
LTCp.refineElementTextures = function (eles) {
var self = this;
// log('refine', eles.length);
self.updateElementsInLayers(eles, function refineEachEle(layer, ele, req) {
var rLyr = layer.replacement;
if (!rLyr) {
rLyr = layer.replacement = self.makeLayer(layer.bb, layer.level);
rLyr.replaces = layer;
rLyr.eles = layer.eles;
// log('make replacement layer %s for %s with level %s', rLyr.id, layer.id, rLyr.level);
}
if (!rLyr.reqs) {
for (var i = 0; i < rLyr.eles.length; i++) {
self.queueLayer(rLyr, rLyr.eles[i]);
}
// log('queue replacement layer refinement', rLyr.id);
}
});
};
LTCp.setupEleCacheInvalidation = function () {
var self = this;
var eleDeqs = [];
if (!useEleTxrCaching) {
return;
}
var updatedElesInLayers = util.debounce(function () {
self.refineElementTextures(eleDeqs);
eleDeqs = [];
}, refineEleDebounceTime);
self.eleTxrCache.onDequeue(function (reqs) {
for (var i = 0; i < reqs.length; i++) {
eleDeqs.push(reqs[i]);
}
updatedElesInLayers();
});
};
LTCp.queueLayer = function (layer, ele) {
var self = this;
var q = self.layersQueue;
var elesQ = layer.elesQueue;
var hasId = elesQ.hasId = elesQ.hasId || {};
// if a layer is going to be replaced, queuing is a waste of time
if (layer.replacement) {
return;
}
if (ele) {
if (hasId[ele.id()]) {
return;
}
elesQ.push(ele);
hasId[ele.id()] = true;
}
if (layer.reqs) {
layer.reqs++;
q.updateItem(layer);
} else {
layer.reqs = 1;
q.push(layer);
}
};
LTCp.dequeue = function (pxRatio) {
var self = this;
var q = self.layersQueue;
var deqd = [];
var eleDeqs = 0;
while (eleDeqs < maxDeqSize) {
if (q.size() === 0) {
break;
}
var layer = q.peek();
// if a layer has been or will be replaced, then don't waste time with it
if (layer.replacement) {
// log('layer %s in queue skipped b/c it already has a replacement', layer.id);
q.pop();
continue;
}
// if this is a replacement layer that has been superceded, then forget it
if (layer.replaces && layer !== layer.replaces.replacement) {
// log('layer is no longer the most uptodate replacement; dequeued', layer.id)
q.pop();
continue;
}
if (layer.invalid) {
// log('replacement layer %s is invalid; dequeued', layer.id);
q.pop();
continue;
}
var ele = layer.elesQueue.shift();
if (ele) {
// log('dequeue layer %s', layer.id);
self.drawEleInLayer(layer, ele, layer.level, pxRatio);
eleDeqs++;
}
if (deqd.length === 0) {
// we need only one entry in deqd to queue redrawing etc
deqd.push(true);
}
// if the layer has all its eles done, then remove from the queue
if (layer.elesQueue.length === 0) {
q.pop();
layer.reqs = 0;
// log('dequeue of layer %s complete', layer.id);
// when a replacement layer is dequeued, it replaces the old layer in the level
if (layer.replaces) {
self.applyLayerReplacement(layer);
}
self.requestRedraw();
}
}
return deqd;
};
LTCp.applyLayerReplacement = function (layer) {
var self = this;
var layersInLevel = self.layersByLevel[layer.level];
var replaced = layer.replaces;
var index = layersInLevel.indexOf(replaced);
// if the replaced layer is not in the active list for the level, then replacing
// refs would be a mistake (i.e. overwriting the true active layer)
if (index < 0 || replaced.invalid) {
// log('replacement layer would have no effect', layer.id);
return;
}
layersInLevel[index] = layer; // replace level ref
// replace refs in eles
for (var i = 0; i < layer.eles.length; i++) {
var _p = layer.eles[i]._private;
var cache = _p.imgLayerCaches = _p.imgLayerCaches || {};
if (cache) {
cache[layer.level] = layer;
}
}
// log('apply replacement layer %s over %s', layer.id, replaced.id);
self.requestRedraw();
};
LTCp.requestRedraw = util.debounce(function () {
var r = this.renderer;
r.redrawHint('eles', true);
r.redrawHint('drag', true);
r.redraw();
}, 100);
LTCp.setupDequeueing = defs.setupDequeueing({
deqRedrawThreshold: deqRedrawThreshold,
deqCost: deqCost,
deqAvgCost: deqAvgCost,
deqNoDrawCost: deqNoDrawCost,
deqFastCost: deqFastCost,
deq: function deq(self, pxRatio) {
return self.dequeue(pxRatio);
},
onDeqd: util.noop,
shouldRedraw: util.trueify,
priority: function priority(self) {
return self.renderer.beforeRenderPriorities.lyrTxrDeq;
}
});
module.exports = LayeredTextureCache;
/***/ }),
/* 127 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CRp = {};
var impl;
CRp.arrowShapeImpl = function (name) {
return (impl || (impl = {
'polygon': function polygon(context, points) {
for (var i = 0; i < points.length; i++) {
var pt = points[i];
context.lineTo(pt.x, pt.y);
}
},
'triangle-backcurve': function triangleBackcurve(context, points, controlPoint) {
var firstPt;
for (var i = 0; i < points.length; i++) {
var pt = points[i];
if (i === 0) {
firstPt = pt;
}
context.lineTo(pt.x, pt.y);
}
context.quadraticCurveTo(controlPoint.x, controlPoint.y, firstPt.x, firstPt.y);
},
'triangle-tee': function triangleTee(context, trianglePoints, teePoints) {
if (context.beginPath) {
context.beginPath();
}
var triPts = trianglePoints;
for (var i = 0; i < triPts.length; i++) {
var pt = triPts[i];
context.lineTo(pt.x, pt.y);
}
if (context.closePath) {
context.closePath();
}
if (context.beginPath) {
context.beginPath();
}
var teePts = teePoints;
var firstTeePt = teePoints[0];
context.moveTo(firstTeePt.x, firstTeePt.y);
for (var i = 0; i < teePts.length; i++) {
var pt = teePts[i];
context.lineTo(pt.x, pt.y);
}
if (context.closePath) {
context.closePath();
}
},
'triangle-cross': function triangleCross(context, trianglePoints, crossLinePoints) {
if (context.beginPath) {
context.beginPath();
}
var triPts = trianglePoints;
for (var i = 0; i < triPts.length; i++) {
var pt = triPts[i];
context.lineTo(pt.x, pt.y);
}
if (context.closePath) {
context.closePath();
}
if (context.beginPath) {
context.beginPath();
}
var teePts = crossLinePoints;
var firstTeePt = crossLinePoints[0];
context.moveTo(firstTeePt.x, firstTeePt.y);
for (var i = 0; i < teePts.length; i++) {
var pt = teePts[i];
context.lineTo(pt.x, pt.y);
}
if (context.closePath) {
context.closePath();
}
},
'circle': function circle(context, rx, ry, r) {
context.arc(rx, ry, r, 0, Math.PI * 2, false);
}
}))[name];
};
module.exports = CRp;
/***/ }),
/* 128 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var CRp = {};
CRp.drawElement = function (context, ele, shiftToOriginWithBb, showLabel) {
var r = this;
if (ele.isNode()) {
r.drawNode(context, ele, shiftToOriginWithBb, showLabel);
} else {
r.drawEdge(context, ele, shiftToOriginWithBb, showLabel);
}
};
CRp.drawCachedElement = function (context, ele, pxRatio, extent) {
var r = this;
var bb = ele.boundingBox();
if (bb.w === 0 || bb.h === 0) {
return;
}
if (!extent || math.boundingBoxesIntersect(bb, extent)) {
var cache = r.data.eleTxrCache.getElement(ele, bb, pxRatio);
if (cache != null) {
context.drawImage(cache.texture.canvas, cache.x, 0, cache.width, cache.height, bb.x1, bb.y1, bb.w, bb.h);
} else {
// if the element is not cacheable, then draw directly
r.drawElement(context, ele);
}
}
};
CRp.drawElements = function (context, eles) {
var r = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
r.drawElement(context, ele);
}
};
CRp.drawCachedElements = function (context, eles, pxRatio, extent) {
var r = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
r.drawCachedElement(context, ele, pxRatio, extent);
}
};
CRp.drawCachedNodes = function (context, eles, pxRatio, extent) {
var r = this;
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
if (!ele.isNode()) {
continue;
}
r.drawCachedElement(context, ele, pxRatio, extent);
}
};
CRp.drawLayeredElements = function (context, eles, pxRatio, extent) {
var r = this;
var layers = r.data.lyrTxrCache.getLayers(eles, pxRatio);
if (layers) {
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
var bb = layer.bb;
if (bb.w === 0 || bb.h === 0) {
continue;
}
context.drawImage(layer.canvas, bb.x1, bb.y1, bb.w, bb.h);
}
} else {
// fall back on plain caching if no layers
r.drawCachedElements(context, eles, pxRatio, extent);
}
};
CRp.drawDebugPoints = function (context, eles) {
var draw = function draw(x, y, color) {
context.fillStyle = color;
context.fillRect(x - 1, y - 1, 3, 3);
};
for (var i = 0; i < eles.length; i++) {
var ele = eles[i];
var rs = ele._private.rscratch;
if (ele.isNode()) {
var p = ele.position();
draw(p.x, p.y, 'magenta');
} else {
var pts = rs.allpts;
for (var j = 0; j + 1 < pts.length; j += 2) {
var x = pts[j];
var y = pts[j + 1];
draw(x, y, 'cyan');
}
draw(rs.midX, rs.midY, 'yellow');
}
}
};
module.exports = CRp;
/***/ }),
/* 129 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CRp = {};
CRp.drawEdge = function (context, edge, shiftToOriginWithBb, drawLabel) {
var r = this;
var rs = edge._private.rscratch;
var usePaths = r.usePaths();
if (!edge.visible()) {
return;
}
// if bezier ctrl pts can not be calculated, then die
if (rs.badLine || rs.allpts == null || isNaN(rs.allpts[0])) {
// isNaN in case edge is impossible and browser bugs (e.g. safari)
return;
}
var bb = void 0;
if (shiftToOriginWithBb) {
bb = shiftToOriginWithBb;
context.translate(-bb.x1, -bb.y1);
}
var overlayPadding = edge.pstyle('overlay-padding').pfValue;
var overlayWidth = 2 * overlayPadding;
var overlayOpacity = edge.pstyle('overlay-opacity').value;
var overlayColor = edge.pstyle('overlay-color').value;
var lineColor = edge.pstyle('line-color').value;
var opacity = edge.pstyle('opacity').value;
var lineStyle = edge.pstyle('line-style').value;
var edgeWidth = edge.pstyle('width').pfValue;
var drawLine = function drawLine() {
var strokeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity;
context.lineWidth = edgeWidth;
context.lineCap = 'butt';
r.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], strokeOpacity);
r.drawEdgePath(edge, context, rs.allpts, lineStyle);
};
var drawOverlay = function drawOverlay() {
var strokeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : overlayOpacity;
context.lineWidth = overlayWidth;
if (rs.edgeType === 'self' && !usePaths) {
context.lineCap = 'butt';
} else {
context.lineCap = 'round';
}
r.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], strokeOpacity);
r.drawEdgePath(edge, context, rs.allpts, 'solid');
};
var drawArrows = function drawArrows() {
var arrowOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : opacity;
r.drawArrowheads(context, edge, arrowOpacity);
};
var drawText = function drawText() {
r.drawElementText(context, edge, drawLabel);
};
context.lineJoin = 'round';
var ghost = edge.pstyle('ghost').value === 'yes';
if (ghost) {
var gx = edge.pstyle('ghost-offset-x').pfValue;
var gy = edge.pstyle('ghost-offset-y').pfValue;
var ghostOpacity = edge.pstyle('ghost-opacity').value;
var effectiveGhostOpacity = opacity * ghostOpacity;
context.translate(gx, gy);
drawLine(effectiveGhostOpacity);
drawArrows(effectiveGhostOpacity);
context.translate(-gx, -gy);
}
drawLine();
drawArrows();
drawOverlay();
drawText();
if (shiftToOriginWithBb) {
context.translate(bb.x1, bb.y1);
}
};
CRp.drawEdgePath = function (edge, context, pts, type) {
var rs = edge._private.rscratch;
var canvasCxt = context;
var path = void 0;
var pathCacheHit = false;
var usePaths = this.usePaths();
if (usePaths) {
var pathCacheKey = pts.join('$');
var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;
if (keyMatches) {
path = context = rs.pathCache;
pathCacheHit = true;
} else {
path = context = new Path2D(); // eslint-disable-line no-undef
rs.pathCacheKey = pathCacheKey;
rs.pathCache = path;
}
}
if (canvasCxt.setLineDash) {
// for very outofdate browsers
switch (type) {
case 'dotted':
canvasCxt.setLineDash([1, 1]);
break;
case 'dashed':
canvasCxt.setLineDash([6, 3]);
break;
case 'solid':
canvasCxt.setLineDash([]);
break;
}
}
if (!pathCacheHit && !rs.badLine) {
if (context.beginPath) {
context.beginPath();
}
context.moveTo(pts[0], pts[1]);
switch (rs.edgeType) {
case 'bezier':
case 'self':
case 'compound':
case 'multibezier':
for (var i = 2; i + 3 < pts.length; i += 4) {
context.quadraticCurveTo(pts[i], pts[i + 1], pts[i + 2], pts[i + 3]);
}
break;
case 'straight':
case 'segments':
case 'haystack':
for (var _i = 2; _i + 1 < pts.length; _i += 2) {
context.lineTo(pts[_i], pts[_i + 1]);
}
break;
}
}
context = canvasCxt;
if (usePaths) {
context.stroke(path);
} else {
context.stroke();
}
// reset any line dashes
if (context.setLineDash) {
// for very outofdate browsers
context.setLineDash([]);
}
};
CRp.drawArrowheads = function (context, edge, opacity) {
var rs = edge._private.rscratch;
var isHaystack = rs.edgeType === 'haystack';
if (!isHaystack) {
this.drawArrowhead(context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle, opacity);
}
this.drawArrowhead(context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle, opacity);
this.drawArrowhead(context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle, opacity);
if (!isHaystack) {
this.drawArrowhead(context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle, opacity);
}
};
CRp.drawArrowhead = function (context, edge, prefix, x, y, angle, opacity) {
if (isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null) {
return;
}
var self = this;
var arrowShape = edge.pstyle(prefix + '-arrow-shape').value;
if (arrowShape === 'none') {
return;
}
var arrowClearFill = edge.pstyle(prefix + '-arrow-fill').value === 'hollow' ? 'both' : 'filled';
var arrowFill = edge.pstyle(prefix + '-arrow-fill').value;
var edgeWidth = edge.pstyle('width').pfValue;
var edgeOpacity = edge.pstyle('opacity').value;
if (opacity === undefined) {
opacity = edgeOpacity;
}
var gco = context.globalCompositeOperation;
if (opacity !== 1 || arrowFill === 'hollow') {
// then extra clear is needed
context.globalCompositeOperation = 'destination-out';
self.fillStyle(context, 255, 255, 255, 1);
self.strokeStyle(context, 255, 255, 255, 1);
self.drawArrowShape(edge, prefix, context, arrowClearFill, edgeWidth, arrowShape, x, y, angle);
context.globalCompositeOperation = gco;
} // otherwise, the opaque arrow clears it for free :)
var color = edge.pstyle(prefix + '-arrow-color').value;
self.fillStyle(context, color[0], color[1], color[2], opacity);
self.strokeStyle(context, color[0], color[1], color[2], opacity);
self.drawArrowShape(edge, prefix, context, arrowFill, edgeWidth, arrowShape, x, y, angle);
};
CRp.drawArrowShape = function (edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) {
var r = this;
var usePaths = this.usePaths();
var rs = edge._private.rscratch;
var pathCacheHit = false;
var path = void 0;
var canvasContext = context;
var translation = { x: x, y: y };
var scale = edge.pstyle('arrow-scale').value;
var size = this.getArrowWidth(edgeWidth, scale);
var shapeImpl = r.arrowShapes[shape];
if (usePaths) {
var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y;
rs.arrowPathCacheKey = rs.arrowPathCacheKey || {};
rs.arrowPathCache = rs.arrowPathCache || {};
var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey;
if (alreadyCached) {
path = context = rs.arrowPathCache[arrowType];
pathCacheHit = true;
} else {
path = context = new Path2D(); // eslint-disable-line no-undef
rs.arrowPathCacheKey[arrowType] = pathCacheKey;
rs.arrowPathCache[arrowType] = path;
}
}
if (context.beginPath) {
context.beginPath();
}
if (!pathCacheHit) {
shapeImpl.draw(context, size, angle, translation, edgeWidth);
}
if (!shapeImpl.leavePathOpen && context.closePath) {
context.closePath();
}
context = canvasContext;
if (fill === 'filled' || fill === 'both') {
if (usePaths) {
context.fill(path);
} else {
context.fill();
}
}
if (fill === 'hollow' || fill === 'both') {
context.lineWidth = shapeImpl.matchEdgeWidth ? edgeWidth : 1;
context.lineJoin = 'miter';
if (usePaths) {
context.stroke(path);
} else {
context.stroke();
}
}
};
module.exports = CRp;
/***/ }),
/* 130 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CRp = {};
CRp.safeDrawImage = function (context, img, ix, iy, iw, ih, x, y, w, h) {
var r = this;
// detect problematic cases for old browsers with bad images (cheaper than try-catch)
if (iw <= 0 || ih <= 0 || w <= 0 || h <= 0) {
return;
}
context.drawImage(img, ix, iy, iw, ih, x, y, w, h);
};
CRp.drawInscribedImage = function (context, img, node, index, nodeOpacity) {
var r = this;
var pos = node.position();
var nodeX = pos.x;
var nodeY = pos.y;
var styleObj = node.cy().style();
var getIndexedStyle = styleObj.getIndexedStyle.bind(styleObj);
var fit = getIndexedStyle(node, 'background-fit', 'value', index);
var repeat = getIndexedStyle(node, 'background-repeat', 'value', index);
var nodeW = node.width();
var nodeH = node.height();
var paddingX2 = node.padding() * 2;
var nodeTW = nodeW + (getIndexedStyle(node, 'background-width-relative-to', 'value', index) === 'inner' ? 0 : paddingX2);
var nodeTH = nodeH + (getIndexedStyle(node, 'background-height-relative-to', 'value', index) === 'inner' ? 0 : paddingX2);
var rs = node._private.rscratch;
var clip = node.pstyle('background-clip').value;
var shouldClip = clip === 'node';
var imgOpacity = getIndexedStyle(node, 'background-image-opacity', 'value', index) * nodeOpacity;
var imgW = img.width || img.cachedW;
var imgH = img.height || img.cachedH;
// workaround for broken browsers like ie
if (null == imgW || null == imgH) {
document.body.appendChild(img); // eslint-disable-line no-undef
imgW = img.cachedW = img.width || img.offsetWidth;
imgH = img.cachedH = img.height || img.offsetHeight;
document.body.removeChild(img); // eslint-disable-line no-undef
}
var w = imgW;
var h = imgH;
if (getIndexedStyle(node, 'background-width', 'value', index) !== 'auto') {
if (getIndexedStyle(node, 'background-width', 'units', index) === '%') {
w = getIndexedStyle(node, 'background-width', 'pfValue', index) * nodeTW;
} else {
w = getIndexedStyle(node, 'background-width', 'pfValue', index);
}
}
if (getIndexedStyle(node, 'background-height', 'value', index) !== 'auto') {
if (getIndexedStyle(node, 'background-height', 'units', index) === '%') {
h = getIndexedStyle(node, 'background-height', 'pfValue', index) * nodeTH;
} else {
h = getIndexedStyle(node, 'background-height', 'pfValue', index);
}
}
if (w === 0 || h === 0) {
return; // no point in drawing empty image (and chrome is broken in this case)
}
if (fit === 'contain') {
var scale = Math.min(nodeTW / w, nodeTH / h);
w *= scale;
h *= scale;
} else if (fit === 'cover') {
var scale = Math.max(nodeTW / w, nodeTH / h);
w *= scale;
h *= scale;
}
var x = nodeX - nodeTW / 2; // left
if (getIndexedStyle(node, 'background-position-x', 'units', index) === '%') {
x += (nodeTW - w) * getIndexedStyle(node, 'background-position-x', 'pfValue', index);
} else {
x += getIndexedStyle(node, 'background-position-x', 'pfValue', index);
}
var y = nodeY - nodeTH / 2; // top
if (getIndexedStyle(node, 'background-position-y', 'units', index) === '%') {
y += (nodeTH - h) * getIndexedStyle(node, 'background-position-y', 'pfValue', index);
} else {
y += getIndexedStyle(node, 'background-position-y', 'pfValue', index);
}
if (rs.pathCache) {
x -= nodeX;
y -= nodeY;
nodeX = 0;
nodeY = 0;
}
var gAlpha = context.globalAlpha;
context.globalAlpha = imgOpacity;
if (repeat === 'no-repeat') {
if (shouldClip) {
context.save();
if (rs.pathCache) {
context.clip(rs.pathCache);
} else {
r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH);
context.clip();
}
}
r.safeDrawImage(context, img, 0, 0, imgW, imgH, x, y, w, h);
if (shouldClip) {
context.restore();
}
} else {
var pattern = context.createPattern(img, repeat);
context.fillStyle = pattern;
r.nodeShapes[r.getNodeShape(node)].draw(context, nodeX, nodeY, nodeTW, nodeTH);
context.translate(x, y);
context.fill();
context.translate(-x, -y);
}
context.globalAlpha = gAlpha;
};
module.exports = CRp;
/***/ }),
/* 131 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var util = __webpack_require__(1);
var math = __webpack_require__(2);
var CRp = {};
CRp.eleTextBiggerThanMin = function (ele, scale) {
if (!scale) {
var zoom = ele.cy().zoom();
var pxRatio = this.getPixelRatio();
var lvl = Math.ceil(math.log2(zoom * pxRatio)); // the effective texture level
scale = Math.pow(2, lvl);
}
var computedSize = ele.pstyle('font-size').pfValue * scale;
var minSize = ele.pstyle('min-zoomed-font-size').pfValue;
if (computedSize < minSize) {
return false;
}
return true;
};
CRp.drawElementText = function (context, ele, force) {
var r = this;
if (force === undefined) {
if (!r.eleTextBiggerThanMin(ele)) {
return;
}
} else {
if (!force) {
return;
}
}
if (ele.isNode()) {
var label = ele.pstyle('label');
if (!label || !label.value) {
return;
}
var textHalign = ele.pstyle('text-halign').strValue;
var textValign = ele.pstyle('text-valign').strValue;
switch (textHalign) {
case 'left':
context.textAlign = 'right';
break;
case 'right':
context.textAlign = 'left';
break;
default:
// e.g. center
context.textAlign = 'center';
}
context.textBaseline = 'bottom';
} else {
var label = ele.pstyle('label');
var srcLabel = ele.pstyle('source-label');
var tgtLabel = ele.pstyle('target-label');
if ((!label || !label.value) && (!srcLabel || !srcLabel.value) && (!tgtLabel || !tgtLabel.value)) {
return;
}
context.textAlign = 'center';
context.textBaseline = 'bottom';
}
r.drawText(context, ele);
if (ele.isEdge()) {
r.drawText(context, ele, 'source');
r.drawText(context, ele, 'target');
}
};
CRp.drawNodeText = CRp.drawEdgeText = CRp.drawElementText;
CRp.getFontCache = function (context) {
var cache;
this.fontCaches = this.fontCaches || [];
for (var i = 0; i < this.fontCaches.length; i++) {
cache = this.fontCaches[i];
if (cache.context === context) {
return cache;
}
}
cache = {
context: context
};
this.fontCaches.push(cache);
return cache;
};
// set up canvas context with font
// returns transformed text string
CRp.setupTextStyle = function (context, ele) {
// Font style
var parentOpacity = ele.effectiveOpacity();
var labelStyle = ele.pstyle('font-style').strValue;
var labelSize = ele.pstyle('font-size').pfValue + 'px';
var labelFamily = ele.pstyle('font-family').strValue;
var labelWeight = ele.pstyle('font-weight').strValue;
var opacity = ele.pstyle('text-opacity').value * ele.pstyle('opacity').value * parentOpacity;
var outlineOpacity = ele.pstyle('text-outline-opacity').value * opacity;
var color = ele.pstyle('color').value;
var outlineColor = ele.pstyle('text-outline-color').value;
var fontCacheKey = ele._private.fontKey;
var cache = this.getFontCache(context);
if (cache.key !== fontCacheKey) {
context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;
cache.key = fontCacheKey;
}
// Calculate text draw position based on text alignment
// so text outlines aren't jagged
context.lineJoin = 'round';
this.fillStyle(context, color[0], color[1], color[2], opacity);
this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);
};
function roundRect(ctx, x, y, width, height, radius) {
var radius = radius || 5;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
ctx.fill();
}
// Draw text
CRp.drawText = function (context, ele, prefix) {
var _p = ele._private;
var rscratch = _p.rscratch;
var parentOpacity = ele.effectiveOpacity();
if (parentOpacity === 0 || ele.pstyle('text-opacity').value === 0) {
return;
}
var textX = util.getPrefixedProperty(rscratch, 'labelX', prefix);
var textY = util.getPrefixedProperty(rscratch, 'labelY', prefix);
var text = this.getLabelText(ele, prefix);
if (text != null && text !== '' && !isNaN(textX) && !isNaN(textY)) {
this.setupTextStyle(context, ele);
var pdash = prefix ? prefix + '-' : '';
var textW = util.getPrefixedProperty(rscratch, 'labelWidth', prefix);
var textH = util.getPrefixedProperty(rscratch, 'labelHeight', prefix);
var textAngle = util.getPrefixedProperty(rscratch, 'labelAngle', prefix);
var marginX = ele.pstyle(pdash + 'text-margin-x').pfValue;
var marginY = ele.pstyle(pdash + 'text-margin-y').pfValue;
var isEdge = ele.isEdge();
var isNode = ele.isNode();
var halign = ele.pstyle('text-halign').value;
var valign = ele.pstyle('text-valign').value;
if (isEdge) {
halign = 'center';
valign = 'center';
}
textX += marginX;
textY += marginY;
var rotation = ele.pstyle(pdash + 'text-rotation');
var theta;
if (rotation.strValue === 'autorotate') {
theta = isEdge ? textAngle : 0;
} else if (rotation.strValue === 'none') {
theta = 0;
} else {
theta = rotation.pfValue;
}
if (theta !== 0) {
var orgTextX = textX;
var orgTextY = textY;
context.translate(orgTextX, orgTextY);
context.rotate(theta);
textX = 0;
textY = 0;
}
switch (valign) {
case 'top':
break;
case 'center':
textY += textH / 2;
break;
case 'bottom':
textY += textH;
break;
}
var backgroundOpacity = ele.pstyle('text-background-opacity').value;
var borderOpacity = ele.pstyle('text-border-opacity').value;
var textBorderWidth = ele.pstyle('text-border-width').pfValue;
var backgroundPadding = ele.pstyle('text-background-padding').pfValue;
if (backgroundOpacity > 0 || textBorderWidth > 0 && borderOpacity > 0) {
var bgX = textX - backgroundPadding;
switch (halign) {
case 'left':
bgX -= textW;
break;
case 'center':
bgX -= textW / 2;
break;
case 'right':
break;
}
var bgY = textY - textH - backgroundPadding;
var bgW = textW + 2 * backgroundPadding;
var bgH = textH + 2 * backgroundPadding;
if (backgroundOpacity > 0) {
var textFill = context.fillStyle;
var textBackgroundColor = ele.pstyle('text-background-color').value;
context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';
var styleShape = ele.pstyle('text-background-shape').strValue;
if (styleShape == 'roundrectangle') {
roundRect(context, bgX, bgY, bgW, bgH, 2);
} else {
context.fillRect(bgX, bgY, bgW, bgH);
}
context.fillStyle = textFill;
}
if (textBorderWidth > 0 && borderOpacity > 0) {
var textStroke = context.strokeStyle;
var textLineWidth = context.lineWidth;
var textBorderColor = ele.pstyle('text-border-color').value;
var textBorderStyle = ele.pstyle('text-border-style').value;
context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';
context.lineWidth = textBorderWidth;
if (context.setLineDash) {
// for very outofdate browsers
switch (textBorderStyle) {
case 'dotted':
context.setLineDash([1, 1]);
break;
case 'dashed':
context.setLineDash([4, 2]);
break;
case 'double':
context.lineWidth = textBorderWidth / 4; // 50% reserved for white between the two borders
context.setLineDash([]);
break;
case 'solid':
context.setLineDash([]);
break;
}
}
context.strokeRect(bgX, bgY, bgW, bgH);
if (textBorderStyle === 'double') {
var whiteWidth = textBorderWidth / 2;
context.strokeRect(bgX + whiteWidth, bgY + whiteWidth, bgW - whiteWidth * 2, bgH - whiteWidth * 2);
}
if (context.setLineDash) {
// for very outofdate browsers
context.setLineDash([]);
}
context.lineWidth = textLineWidth;
context.strokeStyle = textStroke;
}
}
var lineWidth = 2 * ele.pstyle('text-outline-width').pfValue; // *2 b/c the stroke is drawn centred on the middle
if (lineWidth > 0) {
context.lineWidth = lineWidth;
}
if (ele.pstyle('text-wrap').value === 'wrap') {
var lines = util.getPrefixedProperty(rscratch, 'labelWrapCachedLines', prefix);
var lineHeight = textH / lines.length;
switch (valign) {
case 'top':
textY -= (lines.length - 1) * lineHeight;
break;
case 'center':
case 'bottom':
textY -= (lines.length - 1) * lineHeight;
break;
}
for (var l = 0; l < lines.length; l++) {
if (lineWidth > 0) {
context.strokeText(lines[l], textX, textY);
}
context.fillText(lines[l], textX, textY);
textY += lineHeight;
}
} else {
if (lineWidth > 0) {
context.strokeText(text, textX, textY);
}
context.fillText(text, textX, textY);
}
if (theta !== 0) {
context.rotate(-theta);
context.translate(-orgTextX, -orgTextY);
}
}
};
module.exports = CRp;
/***/ }),
/* 132 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* global Path2D */
var is = __webpack_require__(0);
var CRp = {};
CRp.drawNode = function (context, node, shiftToOriginWithBb, drawLabel) {
var r = this;
var nodeWidth = void 0,
nodeHeight = void 0;
var _p = node._private;
var rs = _p.rscratch;
var pos = node.position();
if (!is.number(pos.x) || !is.number(pos.y)) {
return; // can't draw node with undefined position
}
if (!node.visible()) {
return;
}
var parentOpacity = node.effectiveOpacity();
var usePaths = r.usePaths();
var path = void 0;
var pathCacheHit = false;
var padding = node.padding();
nodeWidth = node.width() + 2 * padding;
nodeHeight = node.height() + 2 * padding;
//
// setup shift
var bb = void 0;
if (shiftToOriginWithBb) {
bb = shiftToOriginWithBb;
context.translate(-bb.x1, -bb.y1);
}
//
// load bg image
var bgImgProp = node.pstyle('background-image');
var urls = bgImgProp.value;
var urlDefined = new Array(urls.length);
var image = new Array(urls.length);
var numImages = 0;
for (var i = 0; i < urls.length; i++) {
var url = urls[i];
var defd = urlDefined[i] = url != null && url !== 'none';
if (defd) {
var bgImgCrossOrigin = node.cy().style().getIndexedStyle(node, 'background-image-crossorigin', 'value', i);
numImages++;
// get image, and if not loaded then ask to redraw when later loaded
image[i] = r.getCachedImage(url, bgImgCrossOrigin, function () {
node.emitAndNotify('background');
});
}
}
//
// setup styles
var darkness = node.pstyle('background-blacken').value;
var borderWidth = node.pstyle('border-width').pfValue;
var bgColor = node.pstyle('background-color').value;
var bgOpacity = node.pstyle('background-opacity').value * parentOpacity;
var borderColor = node.pstyle('border-color').value;
var borderStyle = node.pstyle('border-style').value;
var borderOpacity = node.pstyle('border-opacity').value * parentOpacity;
context.lineJoin = 'miter'; // so borders are square with the node shape
var setupShapeColor = function setupShapeColor() {
var bgOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : bgOpacity;
r.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], bgOpy);
};
var setupBorderColor = function setupBorderColor() {
var bdrOpy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : borderOpacity;
r.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], bdrOpy);
};
//
// setup shape
var styleShape = node.pstyle('shape').strValue;
var shapePts = node.pstyle('shape-polygon-points').pfValue;
if (usePaths) {
var pathCacheKey = styleShape + '$' + nodeWidth + '$' + nodeHeight + (styleShape === 'polygon' ? '$' + shapePts.join('$') : '');
context.translate(pos.x, pos.y);
if (rs.pathCacheKey === pathCacheKey) {
path = rs.pathCache;
pathCacheHit = true;
} else {
path = new Path2D();
rs.pathCacheKey = pathCacheKey;
rs.pathCache = path;
}
}
var drawShape = function drawShape() {
if (!pathCacheHit) {
var npos = pos;
if (usePaths) {
npos = {
x: 0,
y: 0
};
}
r.nodeShapes[r.getNodeShape(node)].draw(path || context, npos.x, npos.y, nodeWidth, nodeHeight);
}
if (usePaths) {
context.fill(path);
} else {
context.fill();
}
};
var drawImages = function drawImages() {
var nodeOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : parentOpacity;
var prevBging = _p.backgrounding;
var totalCompleted = 0;
for (var _i = 0; _i < image.length; _i++) {
if (urlDefined[_i] && image[_i].complete && !image[_i].error) {
totalCompleted++;
r.drawInscribedImage(context, image[_i], node, _i, nodeOpacity);
}
}
_p.backgrounding = !(totalCompleted === numImages);
if (prevBging !== _p.backgrounding) {
// update style b/c :backgrounding state changed
node.updateStyle(false);
}
};
var drawPie = function drawPie() {
var redrawShape = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var pieOpacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : parentOpacity;
if (r.hasPie(node)) {
r.drawPie(context, node, pieOpacity);
// redraw/restore path if steps after pie need it
if (redrawShape) {
if (!usePaths) {
r.nodeShapes[r.getNodeShape(node)].draw(context, pos.x, pos.y, nodeWidth, nodeHeight);
}
}
}
};
var darken = function darken() {
var darkenOpacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : parentOpacity;
var opacity = (darkness > 0 ? darkness : -darkness) * darkenOpacity;
var c = darkness > 0 ? 0 : 255;
if (darkness !== 0) {
r.fillStyle(context, c, c, c, opacity);
if (usePaths) {
context.fill(path);
} else {
context.fill();
}
}
};
var drawBorder = function drawBorder() {
if (borderWidth > 0) {
context.lineWidth = borderWidth;
context.lineCap = 'butt';
if (context.setLineDash) {
// for very outofdate browsers
switch (borderStyle) {
case 'dotted':
context.setLineDash([1, 1]);
break;
case 'dashed':
context.setLineDash([4, 2]);
break;
case 'solid':
case 'double':
context.setLineDash([]);
break;
}
}
if (usePaths) {
context.stroke(path);
} else {
context.stroke();
}
if (borderStyle === 'double') {
context.lineWidth = borderWidth / 3;
var gco = context.globalCompositeOperation;
context.globalCompositeOperation = 'destination-out';
if (usePaths) {
context.stroke(path);
} else {
context.stroke();
}
context.globalCompositeOperation = gco;
}
// reset in case we changed the border style
if (context.setLineDash) {
// for very outofdate browsers
context.setLineDash([]);
}
}
};
var drawOverlay = function drawOverlay() {
var overlayPadding = node.pstyle('overlay-padding').pfValue;
var overlayOpacity = node.pstyle('overlay-opacity').value;
var overlayColor = node.pstyle('overlay-color').value;
if (overlayOpacity > 0) {
r.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);
r.nodeShapes['roundrectangle'].draw(context, pos.x, pos.y, nodeWidth + overlayPadding * 2, nodeHeight + overlayPadding * 2);
context.fill();
}
};
var drawText = function drawText() {
r.drawElementText(context, node, drawLabel);
};
var ghost = node.pstyle('ghost').value === 'yes';
if (ghost) {
var gx = node.pstyle('ghost-offset-x').pfValue;
var gy = node.pstyle('ghost-offset-y').pfValue;
var ghostOpacity = node.pstyle('ghost-opacity').value;
var effGhostOpacity = ghostOpacity * parentOpacity;
context.translate(gx, gy);
setupShapeColor(ghostOpacity * bgOpacity);
drawShape();
drawImages(effGhostOpacity);
drawPie(darkness !== 0 || borderWidth !== 0);
darken(effGhostOpacity);
setupBorderColor(ghostOpacity * borderOpacity);
drawBorder();
context.translate(-gx, -gy);
}
setupShapeColor();
drawShape();
drawImages();
drawPie(darkness !== 0 || borderWidth !== 0);
darken();
setupBorderColor();
drawBorder();
if (usePaths) {
context.translate(-pos.x, -pos.y);
}
drawText();
drawOverlay();
//
// clean up shift
if (shiftToOriginWithBb) {
context.translate(bb.x1, bb.y1);
}
};
// does the node have at least one pie piece?
CRp.hasPie = function (node) {
node = node[0]; // ensure ele ref
return node._private.hasPie;
};
CRp.drawPie = function (context, node, nodeOpacity, pos) {
node = node[0]; // ensure ele ref
pos = pos || node.position();
var cyStyle = node.cy().style();
var pieSize = node.pstyle('pie-size');
var x = pos.x;
var y = pos.y;
var nodeW = node.width();
var nodeH = node.height();
var radius = Math.min(nodeW, nodeH) / 2; // must fit in node
var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]
var usePaths = this.usePaths();
if (usePaths) {
x = 0;
y = 0;
}
if (pieSize.units === '%') {
radius = radius * pieSize.pfValue;
} else if (pieSize.pfValue !== undefined) {
radius = pieSize.pfValue / 2;
}
for (var i = 1; i <= cyStyle.pieBackgroundN; i++) {
// 1..N
var size = node.pstyle('pie-' + i + '-background-size').value;
var color = node.pstyle('pie-' + i + '-background-color').value;
var opacity = node.pstyle('pie-' + i + '-background-opacity').value * nodeOpacity;
var percent = size / 100; // map integer range [0, 100] to [0, 1]
// percent can't push beyond 1
if (percent + lastPercent > 1) {
percent = 1 - lastPercent;
}
var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise
var angleDelta = 2 * Math.PI * percent;
var angleEnd = angleStart + angleDelta;
// ignore if
// - zero size
// - we're already beyond the full circle
// - adding the current slice would go beyond the full circle
if (size === 0 || lastPercent >= 1 || lastPercent + percent > 1) {
continue;
}
context.beginPath();
context.moveTo(x, y);
context.arc(x, y, radius, angleStart, angleEnd);
context.closePath();
this.fillStyle(context, color[0], color[1], color[2], opacity);
context.fill();
lastPercent += percent;
}
};
module.exports = CRp;
/***/ }),
/* 133 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CRp = {};
var util = __webpack_require__(1);
var motionBlurDelay = 100;
// var isFirefox = typeof InstallTrigger !== 'undefined';
CRp.getPixelRatio = function () {
var context = this.data.contexts[0];
if (this.forcedPixelRatio != null) {
return this.forcedPixelRatio;
}
var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore; // eslint-disable-line no-undef
};
CRp.paintCache = function (context) {
var caches = this.paintCaches = this.paintCaches || [];
var needToCreateCache = true;
var cache;
for (var i = 0; i < caches.length; i++) {
cache = caches[i];
if (cache.context === context) {
needToCreateCache = false;
break;
}
}
if (needToCreateCache) {
cache = {
context: context
};
caches.push(cache);
}
return cache;
};
CRp.fillStyle = function (context, r, g, b, a) {
context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
// turn off for now, seems context does its own caching
// var cache = this.paintCache(context);
// var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
// if( cache.fillStyle !== fillStyle ){
// context.fillStyle = cache.fillStyle = fillStyle;
// }
};
CRp.strokeStyle = function (context, r, g, b, a) {
context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
// turn off for now, seems context does its own caching
// var cache = this.paintCache(context);
// var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
// if( cache.strokeStyle !== strokeStyle ){
// context.strokeStyle = cache.strokeStyle = strokeStyle;
// }
};
// Resize canvas
CRp.matchCanvasSize = function (container) {
var r = this;
var data = r.data;
var bb = r.findContainerClientCoords();
var width = bb[2];
var height = bb[3];
var pixelRatio = r.getPixelRatio();
var mbPxRatio = r.motionBlurPxRatio;
if (container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] || container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]) {
pixelRatio = mbPxRatio;
}
var canvasWidth = width * pixelRatio;
var canvasHeight = height * pixelRatio;
var canvas;
if (canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight) {
return; // save cycles if same
}
r.fontCaches = null; // resizing resets the style
var canvasContainer = data.canvasContainer;
canvasContainer.style.width = width + 'px';
canvasContainer.style.height = height + 'px';
for (var i = 0; i < r.CANVAS_LAYERS; i++) {
canvas = data.canvases[i];
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}
for (var i = 0; i < r.BUFFER_COUNT; i++) {
canvas = data.bufferCanvases[i];
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}
r.textureMult = 1;
if (pixelRatio <= 1) {
canvas = data.bufferCanvases[r.TEXTURE_BUFFER];
r.textureMult = 2;
canvas.width = canvasWidth * r.textureMult;
canvas.height = canvasHeight * r.textureMult;
}
r.canvasWidth = canvasWidth;
r.canvasHeight = canvasHeight;
};
CRp.renderTo = function (cxt, zoom, pan, pxRatio) {
this.render({
forcedContext: cxt,
forcedZoom: zoom,
forcedPan: pan,
drawAllLayers: true,
forcedPxRatio: pxRatio
});
};
CRp.render = function (options) {
options = options || util.staticEmptyObject();
var forcedContext = options.forcedContext;
var drawAllLayers = options.drawAllLayers;
var drawOnlyNodeLayer = options.drawOnlyNodeLayer;
var forcedZoom = options.forcedZoom;
var forcedPan = options.forcedPan;
var r = this;
var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;
var cy = r.cy;var data = r.data;
var needDraw = data.canvasNeedsRedraw;
var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);
var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;
var mbPxRatio = r.motionBlurPxRatio;
var hasCompoundNodes = cy.hasCompoundNodes();
var inNodeDragGesture = r.hoverData.draggingEles;
var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;
motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;
var motionBlurFadeEffect = motionBlur;
if (!forcedContext) {
if (r.prevPxRatio !== pixelRatio) {
r.invalidateContainerClientCoordsCache();
r.matchCanvasSize(r.container);
r.redrawHint('eles', true);
r.redrawHint('drag', true);
}
r.prevPxRatio = pixelRatio;
}
if (!forcedContext && r.motionBlurTimeout) {
clearTimeout(r.motionBlurTimeout);
}
if (motionBlur) {
if (r.mbFrames == null) {
r.mbFrames = 0;
}
r.mbFrames++;
if (r.mbFrames < 3) {
// need several frames before even high quality motionblur
motionBlurFadeEffect = false;
}
// go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)
if (r.mbFrames > r.minMbLowQualFrames) {
//r.fullQualityMb = false;
r.motionBlurPxRatio = r.mbPxRBlurry;
}
}
if (r.clearingMotionBlur) {
r.motionBlurPxRatio = 1;
}
// b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame
// because a rogue async texture frame would clear needDraw
if (r.textureDrawLastFrame && !textureDraw) {
needDraw[r.NODE] = true;
needDraw[r.SELECT_BOX] = true;
}
var coreStyle = cy.style()._private.coreStyle;
var zoom = cy.zoom();
var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;
var pan = cy.pan();
var effectivePan = {
x: pan.x,
y: pan.y
};
var vp = {
zoom: zoom,
pan: {
x: pan.x,
y: pan.y
}
};
var prevVp = r.prevViewport;
var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y;
// we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)
if (!viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes)) {
r.motionBlurPxRatio = 1;
}
if (forcedPan) {
effectivePan = forcedPan;
}
// apply pixel ratio
effectiveZoom *= pixelRatio;
effectivePan.x *= pixelRatio;
effectivePan.y *= pixelRatio;
var eles = r.getCachedZSortedEles();
function mbclear(context, x, y, w, h) {
var gco = context.globalCompositeOperation;
context.globalCompositeOperation = 'destination-out';
r.fillStyle(context, 255, 255, 255, r.motionBlurTransparency);
context.fillRect(x, y, w, h);
context.globalCompositeOperation = gco;
}
function setContextTransform(context, clear) {
var ePan, eZoom, w, h;
if (!r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG])) {
ePan = {
x: pan.x * mbPxRatio,
y: pan.y * mbPxRatio
};
eZoom = zoom * mbPxRatio;
w = r.canvasWidth * mbPxRatio;
h = r.canvasHeight * mbPxRatio;
} else {
ePan = effectivePan;
eZoom = effectiveZoom;
w = r.canvasWidth;
h = r.canvasHeight;
}
context.setTransform(1, 0, 0, 1, 0, 0);
if (clear === 'motionBlur') {
mbclear(context, 0, 0, w, h);
} else if (!forcedContext && (clear === undefined || clear)) {
context.clearRect(0, 0, w, h);
}
if (!drawAllLayers) {
context.translate(ePan.x, ePan.y);
context.scale(eZoom, eZoom);
}
if (forcedPan) {
context.translate(forcedPan.x, forcedPan.y);
}
if (forcedZoom) {
context.scale(forcedZoom, forcedZoom);
}
}
if (!textureDraw) {
r.textureDrawLastFrame = false;
}
if (textureDraw) {
r.textureDrawLastFrame = true;
var bb;
if (!r.textureCache) {
r.textureCache = {};
bb = r.textureCache.bb = cy.mutableElements().boundingBox();
r.textureCache.texture = r.data.bufferCanvases[r.TEXTURE_BUFFER];
var cxt = r.data.bufferContexts[r.TEXTURE_BUFFER];
cxt.setTransform(1, 0, 0, 1, 0, 0);
cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);
r.render({
forcedContext: cxt,
drawOnlyNodeLayer: true,
forcedPxRatio: pixelRatio * r.textureMult
});
var vp = r.textureCache.viewport = {
zoom: cy.zoom(),
pan: cy.pan(),
width: r.canvasWidth,
height: r.canvasHeight
};
vp.mpan = {
x: (0 - vp.pan.x) / vp.zoom,
y: (0 - vp.pan.y) / vp.zoom
};
}
needDraw[r.DRAG] = false;
needDraw[r.NODE] = false;
var context = data.contexts[r.NODE];
var texture = r.textureCache.texture;
var vp = r.textureCache.viewport;
bb = r.textureCache.bb;
context.setTransform(1, 0, 0, 1, 0, 0);
if (motionBlur) {
mbclear(context, 0, 0, vp.width, vp.height);
} else {
context.clearRect(0, 0, vp.width, vp.height);
}
var outsideBgColor = coreStyle['outside-texture-bg-color'].value;
var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value;
r.fillStyle(context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity);
context.fillRect(0, 0, vp.width, vp.height);
var zoom = cy.zoom();
setContextTransform(context, false);
context.clearRect(vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio);
context.drawImage(texture, vp.mpan.x, vp.mpan.y, vp.width / vp.zoom / pixelRatio, vp.height / vp.zoom / pixelRatio);
} else if (r.textureOnViewport && !forcedContext) {
// clear the cache since we don't need it
r.textureCache = null;
}
var extent = cy.extent();
var vpManip = r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles;
var hideEdges = r.hideEdgesOnViewport && vpManip;
var needMbClear = [];
needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;
if (needMbClear[r.NODE]) {
r.clearedForMotionBlur[r.NODE] = true;
}
needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;
if (needMbClear[r.DRAG]) {
r.clearedForMotionBlur[r.DRAG] = true;
}
if (needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE]) {
var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;
var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] : data.contexts[r.NODE]);
var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;
setContextTransform(context, clear);
if (hideEdges) {
r.drawCachedNodes(context, eles.nondrag, pixelRatio, extent);
} else {
r.drawLayeredElements(context, eles.nondrag, pixelRatio, extent);
}
if (r.debug) {
r.drawDebugPoints(context, eles.nondrag);
}
if (!drawAllLayers && !motionBlur) {
needDraw[r.NODE] = false;
}
}
if (!drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG])) {
var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;
var context = forcedContext || (useBuffer ? r.data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG] : data.contexts[r.DRAG]);
setContextTransform(context, motionBlur && !useBuffer ? 'motionBlur' : undefined);
if (hideEdges) {
r.drawCachedNodes(context, eles.drag, pixelRatio, extent);
} else {
r.drawCachedElements(context, eles.drag, pixelRatio, extent);
}
if (r.debug) {
r.drawDebugPoints(context, eles.drag);
}
if (!drawAllLayers && !motionBlur) {
needDraw[r.DRAG] = false;
}
}
if (r.showFps || !drawOnlyNodeLayer && needDraw[r.SELECT_BOX] && !drawAllLayers) {
var context = forcedContext || data.contexts[r.SELECT_BOX];
setContextTransform(context);
if (r.selection[4] == 1 && (r.hoverData.selecting || r.touchData.selecting)) {
var zoom = r.cy.zoom();
var borderWidth = coreStyle['selection-box-border-width'].value / zoom;
context.lineWidth = borderWidth;
context.fillStyle = 'rgba(' + coreStyle['selection-box-color'].value[0] + ',' + coreStyle['selection-box-color'].value[1] + ',' + coreStyle['selection-box-color'].value[2] + ',' + coreStyle['selection-box-opacity'].value + ')';
context.fillRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]);
if (borderWidth > 0) {
context.strokeStyle = 'rgba(' + coreStyle['selection-box-border-color'].value[0] + ',' + coreStyle['selection-box-border-color'].value[1] + ',' + coreStyle['selection-box-border-color'].value[2] + ',' + coreStyle['selection-box-opacity'].value + ')';
context.strokeRect(r.selection[0], r.selection[1], r.selection[2] - r.selection[0], r.selection[3] - r.selection[1]);
}
}
if (data.bgActivePosistion && !r.hoverData.selecting) {
var zoom = r.cy.zoom();
var pos = data.bgActivePosistion;
context.fillStyle = 'rgba(' + coreStyle['active-bg-color'].value[0] + ',' + coreStyle['active-bg-color'].value[1] + ',' + coreStyle['active-bg-color'].value[2] + ',' + coreStyle['active-bg-opacity'].value + ')';
context.beginPath();
context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI);
context.fill();
}
var timeToRender = r.lastRedrawTime;
if (r.showFps && timeToRender) {
timeToRender = Math.round(timeToRender);
var fps = Math.round(1000 / timeToRender);
context.setTransform(1, 0, 0, 1, 0, 0);
context.fillStyle = 'rgba(255, 0, 0, 0.75)';
context.strokeStyle = 'rgba(255, 0, 0, 0.75)';
context.lineWidth = 1;
context.fillText('1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);
var maxFps = 60;
context.strokeRect(0, 30, 250, 20);
context.fillRect(0, 30, 250 * Math.min(fps / maxFps, 1), 20);
}
if (!drawAllLayers) {
needDraw[r.SELECT_BOX] = false;
}
}
// motionblur: blit rendered blurry frames
if (motionBlur && mbPxRatio !== 1) {
var cxtNode = data.contexts[r.NODE];
var txtNode = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE];
var cxtDrag = data.contexts[r.DRAG];
var txtDrag = r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG];
var drawMotionBlur = function drawMotionBlur(cxt, txt, needClear) {
cxt.setTransform(1, 0, 0, 1, 0, 0);
if (needClear || !motionBlurFadeEffect) {
cxt.clearRect(0, 0, r.canvasWidth, r.canvasHeight);
} else {
mbclear(cxt, 0, 0, r.canvasWidth, r.canvasHeight);
}
var pxr = mbPxRatio;
cxt.drawImage(txt, // img
0, 0, // sx, sy
r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh
0, 0, // x, y
r.canvasWidth, r.canvasHeight // w, h
);
};
if (needDraw[r.NODE] || needMbClear[r.NODE]) {
drawMotionBlur(cxtNode, txtNode, needMbClear[r.NODE]);
needDraw[r.NODE] = false;
}
if (needDraw[r.DRAG] || needMbClear[r.DRAG]) {
drawMotionBlur(cxtDrag, txtDrag, needMbClear[r.DRAG]);
needDraw[r.DRAG] = false;
}
}
r.prevViewport = vp;
if (r.clearingMotionBlur) {
r.clearingMotionBlur = false;
r.motionBlurCleared = true;
r.motionBlur = true;
}
if (motionBlur) {
r.motionBlurTimeout = setTimeout(function () {
r.motionBlurTimeout = null;
r.clearedForMotionBlur[r.NODE] = false;
r.clearedForMotionBlur[r.DRAG] = false;
r.motionBlur = false;
r.clearingMotionBlur = !textureDraw;
r.mbFrames = 0;
needDraw[r.NODE] = true;
needDraw[r.DRAG] = true;
r.redraw();
}, motionBlurDelay);
}
if (!forcedContext) {
cy.emit('render');
}
};
module.exports = CRp;
/***/ }),
/* 134 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var math = __webpack_require__(2);
var CRp = {};
// @O Polygon drawing
CRp.drawPolygonPath = function (context, x, y, width, height, points) {
var halfW = width / 2;
var halfH = height / 2;
if (context.beginPath) {
context.beginPath();
}
context.moveTo(x + halfW * points[0], y + halfH * points[1]);
for (var i = 1; i < points.length / 2; i++) {
context.lineTo(x + halfW * points[i * 2], y + halfH * points[i * 2 + 1]);
}
context.closePath();
};
// Round rectangle drawing
CRp.drawRoundRectanglePath = function (context, x, y, width, height) {
var halfWidth = width / 2;
var halfHeight = height / 2;
var cornerRadius = math.getRoundRectangleRadius(width, height);
if (context.beginPath) {
context.beginPath();
}
// Start at top middle
context.moveTo(x, y - halfHeight);
// Arc from middle top to right side
context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius);
// Arc from right side to bottom
context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);
// Arc from bottom to left side
context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);
// Arc from left side to topBorder
context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius);
// Join line
context.lineTo(x, y - halfHeight);
context.closePath();
};
CRp.drawBottomRoundRectanglePath = function (context, x, y, width, height) {
var halfWidth = width / 2;
var halfHeight = height / 2;
var cornerRadius = math.getRoundRectangleRadius(width, height);
if (context.beginPath) {
context.beginPath();
}
// Start at top middle
context.moveTo(x, y - halfHeight);
context.lineTo(x + halfWidth, y - halfHeight);
context.lineTo(x + halfWidth, y);
context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);
context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);
context.lineTo(x - halfWidth, y - halfHeight);
context.lineTo(x, y - halfHeight);
context.closePath();
};
CRp.drawCutRectanglePath = function (context, x, y, width, height) {
var halfWidth = width / 2;
var halfHeight = height / 2;
var cornerLength = math.getCutRectangleCornerLength();
if (context.beginPath) {
context.beginPath();
}
context.moveTo(x - halfWidth + cornerLength, y - halfHeight);
context.lineTo(x + halfWidth - cornerLength, y - halfHeight);
context.lineTo(x + halfWidth, y - halfHeight + cornerLength);
context.lineTo(x + halfWidth, y + halfHeight - cornerLength);
context.lineTo(x + halfWidth - cornerLength, y + halfHeight);
context.lineTo(x - halfWidth + cornerLength, y + halfHeight);
context.lineTo(x - halfWidth, y + halfHeight - cornerLength);
context.lineTo(x - halfWidth, y - halfHeight + cornerLength);
context.closePath();
};
CRp.drawBarrelPath = function (context, x, y, width, height) {
var halfWidth = width / 2;
var halfHeight = height / 2;
var xBegin = x - halfWidth;
var xEnd = x + halfWidth;
var yBegin = y - halfHeight;
var yEnd = y + halfHeight;
var barrelCurveConstants = math.getBarrelCurveConstants(width, height);
var wOffset = barrelCurveConstants.widthOffset;
var hOffset = barrelCurveConstants.heightOffset;
var ctrlPtXOffset = barrelCurveConstants.ctrlPtOffsetPct * wOffset;
if (context.beginPath) {
context.beginPath();
}
context.moveTo(xBegin, yBegin + hOffset);
context.lineTo(xBegin, yEnd - hOffset);
context.quadraticCurveTo(xBegin + ctrlPtXOffset, yEnd, xBegin + wOffset, yEnd);
context.lineTo(xEnd - wOffset, yEnd);
context.quadraticCurveTo(xEnd - ctrlPtXOffset, yEnd, xEnd, yEnd - hOffset);
context.lineTo(xEnd, yBegin + hOffset);
context.quadraticCurveTo(xEnd - ctrlPtXOffset, yBegin, xEnd - wOffset, yBegin);
context.lineTo(xBegin + wOffset, yBegin);
context.quadraticCurveTo(xBegin + ctrlPtXOffset, yBegin, xBegin, yBegin + hOffset);
context.closePath();
};
var sin0 = Math.sin(0);
var cos0 = Math.cos(0);
var sin = {};
var cos = {};
var ellipseStepSize = Math.PI / 40;
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) {
sin[i] = Math.sin(i);
cos[i] = Math.cos(i);
}
CRp.drawEllipsePath = function (context, centerX, centerY, width, height) {
if (context.beginPath) {
context.beginPath();
}
if (context.ellipse) {
context.ellipse(centerX, centerY, width / 2, height / 2, 0, 0, 2 * Math.PI);
} else {
var xPos, yPos;
var rw = width / 2;
var rh = height / 2;
for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize) {
xPos = centerX - rw * sin[i] * sin0 + rw * cos[i] * cos0;
yPos = centerY + rh * cos[i] * sin0 + rh * sin[i] * cos0;
if (i === 0) {
context.moveTo(xPos, yPos);
} else {
context.lineTo(xPos, yPos);
}
}
}
context.closePath();
};
module.exports = CRp;
/***/ }),
/* 135 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var CRp = {};
CRp.createBuffer = function (w, h) {
var buffer = document.createElement('canvas'); // eslint-disable-line no-undef
buffer.width = w;
buffer.height = h;
return [buffer, buffer.getContext('2d')];
};
CRp.bufferCanvasImage = function (options) {
var cy = this.cy;
var eles = cy.mutableElements();
var bb = eles.boundingBox();
var ctrRect = this.findContainerClientCoords();
var width = options.full ? Math.ceil(bb.w) : ctrRect[2];
var height = options.full ? Math.ceil(bb.h) : ctrRect[3];
var specdMaxDims = is.number(options.maxWidth) || is.number(options.maxHeight);
var pxRatio = this.getPixelRatio();
var scale = 1;
if (options.scale !== undefined) {
width *= options.scale;
height *= options.scale;
scale = options.scale;
} else if (specdMaxDims) {
var maxScaleW = Infinity;
var maxScaleH = Infinity;
if (is.number(options.maxWidth)) {
maxScaleW = scale * options.maxWidth / width;
}
if (is.number(options.maxHeight)) {
maxScaleH = scale * options.maxHeight / height;
}
scale = Math.min(maxScaleW, maxScaleH);
width *= scale;
height *= scale;
}
if (!specdMaxDims) {
width *= pxRatio;
height *= pxRatio;
scale *= pxRatio;
}
var buffCanvas = document.createElement('canvas'); // eslint-disable-line no-undef
buffCanvas.width = width;
buffCanvas.height = height;
buffCanvas.style.width = width + 'px';
buffCanvas.style.height = height + 'px';
var buffCxt = buffCanvas.getContext('2d');
// Rasterize the layers, but only if container has nonzero size
if (width > 0 && height > 0) {
buffCxt.clearRect(0, 0, width, height);
buffCxt.globalCompositeOperation = 'source-over';
var zsortedEles = this.getCachedZSortedEles();
if (options.full) {
// draw the full bounds of the graph
buffCxt.translate(-bb.x1 * scale, -bb.y1 * scale);
buffCxt.scale(scale, scale);
this.drawElements(buffCxt, zsortedEles);
buffCxt.scale(1 / scale, 1 / scale);
buffCxt.translate(bb.x1 * scale, bb.y1 * scale);
} else {
// draw the current view
var pan = cy.pan();
var translation = {
x: pan.x * scale,
y: pan.y * scale
};
scale *= cy.zoom();
buffCxt.translate(translation.x, translation.y);
buffCxt.scale(scale, scale);
this.drawElements(buffCxt, zsortedEles);
buffCxt.scale(1 / scale, 1 / scale);
buffCxt.translate(-translation.x, -translation.y);
}
// need to fill bg at end like this in order to fill cleared transparent pixels in jpgs
if (options.bg) {
buffCxt.globalCompositeOperation = 'destination-over';
buffCxt.fillStyle = options.bg;
buffCxt.rect(0, 0, width, height);
buffCxt.fill();
}
}
return buffCanvas;
};
function b64ToBlob(b64, mimeType) {
var bytes = atob(b64);
var buff = new ArrayBuffer(bytes.length);
var buffUint8 = new Uint8Array(buff);
for (var i = 0; i < bytes.length; i++) {
buffUint8[i] = bytes.charCodeAt(i);
}
return new Blob([buff], { type: mimeType });
}
function b64UriToB64(b64uri) {
var i = b64uri.indexOf(',');
return b64uri.substr(i + 1);
};
function output(options, canvas, mimeType) {
var b64Uri = canvas.toDataURL(mimeType, options.quality);
switch (options.output) {
case 'blob':
return b64ToBlob(b64UriToB64(b64Uri), mimeType);
case 'base64':
return b64UriToB64(b64Uri);
case 'base64uri':
default:
return b64Uri;
}
}
CRp.png = function (options) {
return output(options, this.bufferCanvasImage(options), 'image/png');
};
CRp.jpg = function (options) {
return output(options, this.bufferCanvasImage(options), 'image/jpeg');
};
module.exports = CRp;
/***/ }),
/* 136 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var CRp = {};
CRp.nodeShapeImpl = function (name, context, centerX, centerY, width, height, points) {
switch (name) {
case 'ellipse':
return this.drawEllipsePath(context, centerX, centerY, width, height);
case 'polygon':
return this.drawPolygonPath(context, centerX, centerY, width, height, points);
case 'roundrectangle':
return this.drawRoundRectanglePath(context, centerX, centerY, width, height);
case 'cutrectangle':
return this.drawCutRectanglePath(context, centerX, centerY, width, height);
case 'bottomroundrectangle':
return this.drawBottomRoundRectanglePath(context, centerX, centerY, width, height);
case 'barrel':
return this.drawBarrelPath(context, centerX, centerY, width, height);
}
};
module.exports = CRp;
/***/ }),
/* 137 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var is = __webpack_require__(0);
var util = __webpack_require__(1);
var Style = __webpack_require__(18);
// a dummy stylesheet object that doesn't need a reference to the core
// (useful for init)
var Stylesheet = function Stylesheet() {
if (!(this instanceof Stylesheet)) {
return new Stylesheet();
}
this.length = 0;
};
var sheetfn = Stylesheet.prototype;
sheetfn.instanceString = function () {
return 'stylesheet';
};
// just store the selector to be parsed later
sheetfn.selector = function (selector) {
var i = this.length++;
this[i] = {
selector: selector,
properties: []
};
return this; // chaining
};
// just store the property to be parsed later
sheetfn.css = function (name, value) {
var i = this.length - 1;
if (is.string(name)) {
this[i].properties.push({
name: name,
value: value
});
} else if (is.plainObject(name)) {
var map = name;
for (var j = 0; j < Style.properties.length; j++) {
var prop = Style.properties[j];
var mapVal = map[prop.name];
if (mapVal === undefined) {
// also try camel case name
mapVal = map[util.dash2camel(prop.name)];
}
if (mapVal !== undefined) {
var _name = prop.name;
var _value = mapVal;
this[i].properties.push({
name: _name,
value: _value
});
}
}
}
return this; // chaining
};
sheetfn.style = sheetfn.css;
// generate a real style object from the dummy stylesheet
sheetfn.generateStyle = function (cy) {
var style = new Style(cy);
return this.appendToStyle(style);
};
// append a dummy stylesheet object on a real style object
sheetfn.appendToStyle = function (style) {
for (var i = 0; i < this.length; i++) {
var context = this[i];
var selector = context.selector;
var props = context.properties;
style.selector(selector); // apply selector
for (var j = 0; j < props.length; j++) {
var prop = props[j];
style.css(prop.name, prop.value); // apply property
}
}
return style;
};
module.exports = Stylesheet;
/***/ }),
/* 138 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = "3.2.20";
/***/ })
/******/ ]);
});