aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-ui/non_bower_components/cytoscape.js-edge-editation
diff options
context:
space:
mode:
Diffstat (limited to 'catalog-ui/non_bower_components/cytoscape.js-edge-editation')
-rw-r--r--catalog-ui/non_bower_components/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js554
-rw-r--r--catalog-ui/non_bower_components/cytoscape.js-edge-editation/README.md58
-rw-r--r--catalog-ui/non_bower_components/cytoscape.js-edge-editation/index.html169
3 files changed, 781 insertions, 0 deletions
diff --git a/catalog-ui/non_bower_components/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js
new file mode 100644
index 0000000000..147f19ce54
--- /dev/null
+++ b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js
@@ -0,0 +1,554 @@
+(function (scope) {
+ var Class = function (param1, param2) {
+
+ var extend, mixins, definition;
+ if (param2) { //two parameters passed, first is extends, second definition object
+ extend = Array.isArray(param1) ? param1[0] : param1;
+ mixins = Array.isArray(param1) ? param1.slice(1) : null;
+ definition = param2;
+ } else { //only one parameter passed => no extend, only definition
+ extend = null;
+ definition = param1;
+ }
+
+
+ var Definition = definition.hasOwnProperty("constructor") ? definition.constructor : function () {
+ };
+
+ Definition.prototype = Object.create(extend ? extend.prototype : null);
+ var propertiesObject = definition.propertiesObject ? definition.propertiesObject : {};
+ if (mixins) {
+ var i, i2;
+ for (i in mixins) {
+ for (i2 in mixins[i].prototype) {
+ Definition.prototype[i2] = mixins[i].prototype[i2];
+ }
+ for (var i2 in mixins[i].prototype.propertiesObject) {
+ propertiesObject[i2] = mixins[i].prototype.propertiesObject[i2];
+ }
+ }
+ }
+
+ Definition.prototype.propertiesObject = propertiesObject;
+
+ Object.defineProperties(Definition.prototype, propertiesObject);
+
+ for (var key in definition) {
+ if (definition.hasOwnProperty(key)) {
+ Definition.prototype[key] = definition[key];
+ }
+ }
+
+ Definition.prototype.constructor = Definition;
+
+ return Definition;
+ };
+
+
+ var Interface = function (properties) {
+ this.properties = properties;
+ };
+
+ var InterfaceException = function (message) {
+ this.name = "InterfaceException";
+ this.message = message || "";
+ };
+
+ InterfaceException.prototype = new Error();
+
+ Interface.prototype.implements = function (target) {
+ for (var i in this.properties) {
+ if (target[this.properties[i]] == undefined) {
+ throw new InterfaceException("Missing property " + this.properties[i]);
+ }
+ }
+ return true;
+ };
+
+ Interface.prototype.doesImplement = function (target) {
+ for (var i in this.properties) {
+ if (target[this.properties[i]] === undefined) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ var VectorMath = {
+ distance: function (vector1, vector2) {
+ return Math.sqrt(Math.pow(vector1.x - vector2.x, 2) + Math.pow(vector1.y - vector2.y, 2));
+ }
+ };
+
+ var EventDispatcher = Class({
+ constructor: function () {
+ this.events = {};
+ },
+ on: function (name, listener, context) {
+ this.events[name] = this.events[name] ? this.events[name] : [];
+ this.events[name].push({
+ listener: listener,
+ context: context
+ })
+ },
+ once: function (name, listener, context) {
+ this.off(name, listener, context);
+ this.on(name, listener, context);
+ },
+ off: function (name, listener, context) {
+ //no event with this name registered? => finish
+ if (!this.events[name]) {
+ return;
+ }
+ if (listener) { //searching only for certains listeners
+ for (var i in this.events[name]) {
+ if (this.events[name][i].listener === listener) {
+ if (!context || this.events[name][i].context === context) {
+ this.events[name].splice(i, 1);
+ }
+ }
+ }
+ } else {
+ delete this.events[name];
+ }
+ },
+ trigger: function (name) {
+ var listeners = this.events[name];
+
+ for (var i in listeners) {
+ listeners[i].listener.apply(listeners[i].context, Array.prototype.slice.call(arguments, 1));
+ }
+ }
+ });
+
+ scope.CytoscapeEdgeEditation = Class({
+
+ init: function (cy, handleSize) {
+ this.DOUBLE_CLICK_INTERVAL = 300;
+ this.HANDLE_SIZE = handleSize ? handleSize : 5;
+ this.ARROW_END_ID = "ARROW_END_ID";
+
+ this._handles = {};
+ this._dragging = false;
+ this._hover = null;
+
+
+ this._cy = cy;
+ this._$container = $(cy.container());
+
+ this._cy.on('mouseover tap', 'node', this._mouseOver.bind(this));
+ this._cy.on('mouseout', 'node', this._mouseOut.bind(this));
+
+ this._$container.on('mouseout', function (e) {
+ if (this.permanentHandle) {
+ return;
+ }
+
+ this._clear();
+ }.bind(this));
+
+ this._$container.on('mouseover', function (e) {
+ if (this._hover) {
+ this._mouseOver({cyTarget: this._hover});
+ }
+ }.bind(this));
+
+ this._cy.on("select", "node", this._redraw.bind(this))
+
+ this._cy.on("mousedown", "node", function () {
+ this._nodeClicked = true;
+ }.bind(this));
+
+ this._cy.on("mouseup", "node", function () {
+ this._nodeClicked = false;
+ }.bind(this));
+
+ this._cy.on("remove", "node", function () {
+ this._hover = false;
+ this._clear();
+ }.bind(this));
+
+ this._cy.on('showhandle', function (cy, target) {
+ this.permanentHandle = true;
+ this._showHandles(target);
+ }.bind(this));
+
+ this._cy.on('hidehandles', this._hideHandles.bind(this));
+
+ this._cy.bind('zoom pan', this._redraw.bind(this));
+
+
+ this._$canvas = $('<canvas></canvas>');
+ this._$canvas.css("top", 0);
+ this._$canvas.on("mousedown", this._mouseDown.bind(this));
+ this._$canvas.on("mousemove", this._mouseMove.bind(this));
+
+ this._ctx = this._$canvas[0].getContext('2d');
+ this._$container.children("div").append(this._$canvas);
+
+ $(window).bind('mouseup', this._mouseUp.bind(this));
+
+ /*$(window).bind('resize', this._resizeCanvas.bind(this));
+ $(window).bind('resize', this._resizeCanvas.bind(this));*/
+
+ this._cy.on("resize", this._resizeCanvas.bind(this));
+
+ this._$container.bind('resize', function () {
+ this._resizeCanvas();
+ }.bind(this));
+
+ this._resizeCanvas();
+
+ this._arrowEnd = this._cy.add({
+ group: "nodes",
+ data: {
+ "id": this.ARROW_END_ID,
+ "position": {x: 150, y: 150}
+ }
+ });
+
+ this._arrowEnd.css({
+ "opacity": 0,
+ 'width': 0.0001,
+ 'height': 0.0001
+ });
+
+ },
+ registerHandle: function (handle) {
+ if (handle.nodeTypeNames) {
+ for (var i in handle.nodeTypeNames) {
+ var nodeTypeName = handle.nodeTypeNames[i];
+ this._handles[nodeTypeName] = this._handles[nodeTypeName] || [];
+ this._handles[nodeTypeName].push(handle);
+ }
+ } else {
+ this._handles["*"] = this._handles["*"] || [];
+ this._handles["*"].push(handle);
+ }
+
+ },
+ _showHandles: function (target) {
+ var nodeTypeName = target.data().type;
+ if (nodeTypeName) {
+
+ var handles = this._handles[nodeTypeName] ? this._handles[nodeTypeName] : this._handles["*"];
+
+ for (var i in handles) {
+ if (handles[i].type != null) {
+ this._drawHandle(handles[i], target);
+ }
+ }
+ }
+
+ },
+ _clear: function () {
+
+ var w = this._$container.width();
+ var h = this._$container.height();
+ this._ctx.clearRect(0, 0, w, h);
+ },
+ _drawHandle: function (handle, target) {
+
+ var position = this._getHandlePosition(handle, target);
+
+ this._ctx.beginPath();
+
+ if (handle.imageUrl) {
+ var base_image = new Image();
+ base_image.src = handle.imageUrl;
+ this._ctx.drawImage(base_image, position.x, position.y, this.HANDLE_SIZE, this.HANDLE_SIZE);
+ } else {
+ this._ctx.arc(position.x, position.y, this.HANDLE_SIZE, 0, 2 * Math.PI, false);
+ this._ctx.fillStyle = handle.color;
+ this._ctx.strokeStyle = "white";
+ this._ctx.lineWidth = 0;
+ this._ctx.fill();
+ this._ctx.stroke();
+ }
+
+ },
+ _drawArrow: function (fromNode, toPosition, handle) {
+ var toNode;
+ if (this._hover) {
+ toNode = this._hover;
+ } else {
+ this._arrowEnd.renderedPosition(toPosition);
+ toNode = this._arrowEnd;
+ }
+
+
+ if (this._edge) {
+ this._edge.remove();
+ }
+
+ this._edge = this._cy.add({
+ group: "edges",
+ data: {
+ id: "edge",
+ source: fromNode.id(),
+ target: toNode.id(),
+ type: 'temporary-link'
+ },
+ css: $.extend(
+ this._getEdgeCSSByHandle(handle),
+ {opacity: 0.5}
+ )
+ });
+
+ },
+ _clearArrow: function () {
+ if (this._edge) {
+ this._edge.remove();
+ this._edge = null;
+ }
+ },
+ _resizeCanvas: function () {
+ this._$canvas
+ .attr('height', this._$container.height())
+ .attr('width', this._$container.width())
+ .css({
+ 'position': 'absolute',
+ 'z-index': '999'
+ });
+ },
+ _mouseDown: function (e) {
+ this._hit = this._hitTestHandles(e);
+
+ if (this._hit) {
+ this._lastClick = Date.now();
+ this._dragging = this._hover;
+ this._hover = null;
+ e.stopImmediatePropagation();
+ }
+ },
+ _hideHandles: function () {
+ this.permanentHandle = false;
+ this._clear();
+
+ if(this._hover){
+ this._showHandles(this._hover);
+ }
+ },
+ _mouseUp: function () {
+ if (this._hover) {
+ if (this._hit) {
+ //check if custom listener was passed, if so trigger it and do not add edge
+ var listeners = this._cy._private.listeners;
+ for (var i = 0; i < listeners.length; i++) {
+ if (listeners[i].type === 'addedgemouseup') {
+ this._cy.trigger('addedgemouseup', {
+ source: this._dragging,
+ target: this._hover,
+ edge: this._edge
+ });
+ var that = this;
+ setTimeout(function () {
+ that._dragging = false;
+ that._clearArrow();
+ that._hit = null;
+ }, 0);
+
+
+ return;
+ }
+ }
+
+ var edgeToRemove = this._checkSingleEdge(this._hit.handle, this._dragging);
+ if (edgeToRemove) {
+ this._cy.remove("#" + edgeToRemove.id());
+ }
+ var edge = this._cy.add({
+ data: {
+ source: this._dragging.id(),
+ target: this._hover.id(),
+ type: this._hit.handle.type
+ }
+ });
+ this._initEdgeEvents(edge);
+ }
+ }
+ this._cy.trigger('handlemouseout', {
+ node: this._hover
+ });
+ $("body").css("cursor", "inherit");
+ this._dragging = false;
+ this._clearArrow();
+ },
+ _mouseMove: function (e) {
+ if (this._hover) {
+ if (!this._dragging) {
+ var hit = this._hitTestHandles(e);
+ if (hit) {
+ this._cy.trigger('handlemouseover', {
+ node: this._hover
+ });
+ $("body").css("cursor", "pointer");
+
+ } else {
+ this._cy.trigger('handlemouseout', {
+ node: this._hover
+ });
+ $("body").css("cursor", "inherit");
+ }
+ }
+ } else {
+ $("body").css("cursor", "inherit");
+ }
+
+ if (this._dragging && this._hit.handle) {
+ this._drawArrow(this._dragging, this._getRelativePosition(e), this._hit.handle);
+ }
+
+ if (this._nodeClicked) {
+ this._clear();
+ }
+ },
+ _mouseOver: function (e) {
+
+ if (this._dragging) {
+ if ( (e.cyTarget.id() != this._dragging.id()) && e.cyTarget.data().allowConnection || this._hit.handle.allowLoop) {
+ this._hover = e.cyTarget;
+ }
+ } else {
+ this._hover = e.cyTarget;
+ this._showHandles(this._hover);
+ }
+ },
+ _mouseOut: function (e) {
+ if(!this._dragging) {
+ if (this.permanentHandle) {
+ return;
+ }
+
+ this._clear();
+ }
+ this._hover = null;
+ },
+ _removeEdge: function (edge) {
+ edge.off("mousedown");
+ this._cy.remove("#" + edge.id());
+ },
+ _initEdgeEvents: function (edge) {
+ var self = this;
+ edge.on("mousedown", function () {
+ if (self.__lastClick && Date.now() - self.__lastClick < self.DOUBLE_CLICK_INTERVAL) {
+ self._removeEdge(this);
+ }
+ self.__lastClick = Date.now();
+ })
+ },
+ _hitTestHandles: function (e) {
+ var mousePoisition = this._getRelativePosition(e);
+
+ if (this._hover) {
+ var nodeTypeName = this._hover.data().type;
+ if (nodeTypeName) {
+ var handles = this._handles[nodeTypeName] ? this._handles[nodeTypeName] : this._handles["*"];
+
+ for (var i in handles) {
+ var handle = handles[i];
+
+ var position = this._getHandlePosition(handle, this._hover);
+ if (VectorMath.distance(position, mousePoisition) < this.HANDLE_SIZE) {
+ return {
+ handle: handle,
+ position: position
+ };
+ }
+ }
+ }
+ }
+ },
+ _getHandlePosition: function (handle, target) {
+ var position = target.renderedPosition();
+ var width = target.renderedOuterWidth();
+ var height = target.renderedOuterHeight();
+ var xpos = null;
+ var ypos = null;
+
+ switch (handle.positionX) {
+ case "left":
+ xpos = position.x - width / 2 + this.HANDLE_SIZE;
+ break;
+ case "right":
+ xpos = position.x + width / 2 - this.HANDLE_SIZE;
+ break;
+ case "center":
+ xpos = position.x;
+ break;
+ }
+
+ switch (handle.positionY) {
+ case "top":
+ ypos = position.y - height / 2 + this.HANDLE_SIZE;
+ break;
+ case "center":
+ ypos = position.y;
+ break;
+ case "bottom":
+ ypos = position.y + height / 2 - this.HANDLE_SIZE;
+ break;
+ }
+
+ var offsetX = handle.offsetX ? handle.offsetX : 0;
+ var offsetY = handle.offsetY ? handle.offsetY : 0;
+ return {x: xpos + offsetX, y: ypos + offsetY};
+ },
+ _getEdgeCSSByHandle: function (handle) {
+ var color = handle.lineColor ? handle.lineColor : handle.color;
+ return {
+ "line-color": color,
+ "target-arrow-color": color,
+ "line-style": handle.lineStyle? handle.lineStyle: 'solid',
+ "width": handle.width? handle.width : 3
+ };
+ },
+ _getHandleByType: function (type) {
+ for (var i in this._handles) {
+ var byNodeType = this._handles[i];
+ for (var i2 in byNodeType) {
+ var handle = byNodeType[i2];
+ if (handle.type == type) {
+ return handle;
+ }
+ }
+ }
+ },
+ _getRelativePosition: function (e) {
+ var containerPosition = this._$container.offset();
+ return {
+ x: e.pageX - containerPosition.left,
+ y: e.pageY - containerPosition.top
+ }
+ },
+ _checkSingleEdge: function (handle, node) {
+
+ if (handle.noMultigraph) {
+ var edges = this._cy.edges("[source='" + this._hover.id() + "'][target='" + node.id() + "'],[source='" + node.id() + "'][target='" + this._hover.id() + "']");
+
+ for (var i = 0; i < edges.length; i++) {
+ return edges[i];
+ }
+ } else {
+
+ if (handle.single == false) {
+ return;
+ }
+ var edges = this._cy.edges("[source='" + node.id() + "']");
+
+ for (var i = 0; i < edges.length; i++) {
+ if (edges[i].data()["type"] == handle.type) {
+ return edges[i];
+ }
+ }
+ }
+ },
+ _redraw: function () {
+ this._clear();
+ if (this._hover) {
+ this._showHandles(this._hover);
+ }
+ }
+ });
+
+})(this); \ No newline at end of file
diff --git a/catalog-ui/non_bower_components/cytoscape.js-edge-editation/README.md b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/README.md
new file mode 100644
index 0000000000..909dcb06d1
--- /dev/null
+++ b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/README.md
@@ -0,0 +1,58 @@
+# cytoscape.js-edge-editation
+Extension for Cytoscape.js, which adds handles to nodes and allows to create different types of edges
+
+
+## Dependencies
+
+Extension was tested with these versions of libraries:
+
+* jQuery 2.1.1
+* Cytoscape.js 2.6.0
+
+## Install
+
+Use git clone or direct zip download and unpack archive into your project. Then, simply insert \<script\> tag after
+Cytoscape.js and jQuery:
+
+```html
+<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
+<script src="cytoscape.js"></script>
+<script src="CytoscapeEdgeEditation.js"></script>
+```
+
+## How to use
+
+First, you need to initialize extension. After initializing Cytoscape.js:
+
+```js
+var cy = cytoscape({...});
+var handles = new CytoscapeEdgeEditation;
+handles.init(cy);
+```
+
+Then, you need to register handles to certain node types:
+
+```js
+handles.registerHandle({
+ positionX: "left", //horizontal position of the handle (left | center | right)
+ positionY: "center", //vertical position of the handle (top | center | bottom)
+ color: "#48FF00", //color of the handle
+ type: "some_type", //stored as data() attribute, can be used for styling
+ single: true, //wheter only one edge of this type can start from same node (default false)
+ nodeTypeNames: ["type2"] //which types of nodes will contain this handle
+ noMultigraph: false //whereter two nodes can't be connected with multiple edges (does not consider orientation)
+});
+
+handles.registerHandle({...});
+handles.registerHandle({...});
+```
+
+Type of node is stored in data section:
+
+```js
+cy.add({
+ data: { id: 'n4', type: "type2"},
+});
+```
+![Screenshot](http://i.imgbox.com/drCuXQqu.png)
+![Screenshot](http://i.imgbox.com/23jr7qPa.png)
diff --git a/catalog-ui/non_bower_components/cytoscape.js-edge-editation/index.html b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/index.html
new file mode 100644
index 0000000000..d19fd36c24
--- /dev/null
+++ b/catalog-ui/non_bower_components/cytoscape.js-edge-editation/index.html
@@ -0,0 +1,169 @@
+<!doctype html>
+<html lang="cs">
+<head>
+ <meta charset="UTF-8">
+ <title>CytoscapeEdgeEditation</title>
+ <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
+ <script src="bower_components/cytoscape/dist/cytoscape.js"></script>
+ <script src="CytoscapeEdgeEditation.js"></script>
+ <script>
+ $(function(){
+ //INITIALIZATION
+ var domContainer = $(".cy");
+ var cy = cytoscape({
+ container: domContainer,
+ style: [
+ {
+ selector: 'node[type="type1"]',
+ style: {
+ 'background-color': '#FFEB12',
+ }
+ },
+ {
+ selector: 'node[type="type2"]',
+ style: {
+ 'background-color': '#2CE8F2',
+ }
+ },
+ {
+ selector: 'edge',
+ style: {
+ 'width': 3,
+ 'target-arrow-shape': 'triangle'
+ }
+ },
+ {
+ selector: 'edge[type="default"]',
+ style: {
+ 'line-color': 'green',
+ 'target-arrow-color': 'green',
+ }
+ },
+ {
+ selector: 'edge[type="yes"]',
+ style: {
+ 'line-color': '#48FF00',
+ 'target-arrow-color': '#48FF00',
+ }
+ },
+ {
+ selector: 'edge[type="no"]',
+ style: {
+ 'line-color': '#ED1000',
+ 'target-arrow-color': '#ED1000',
+ }
+ }
+ ]
+ });
+
+
+ var handles = new CytoscapeEdgeEditation;
+ handles.init(cy);
+
+ handles.registerHandle({
+ positionX: "center",
+ positionY: "bottom",
+ color: "green",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["type1"]
+ });
+
+ handles.registerHandle({
+ positionX: "center",
+ positionY: "top",
+ color: "green",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["type1"]
+ });
+
+ handles.registerHandle({
+ positionX: "left",
+ positionY: "center",
+ color: "green",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["type1"]
+ });
+
+ handles.registerHandle({
+ positionX: "right",
+ positionY: "center",
+ color: "green",
+ type: "default",
+ single: false,
+ nodeTypeNames: ["type1"]
+ // noMultigraph: true
+ });
+
+ handles.registerHandle({
+ positionX: "left",
+ positionY: "center",
+ color: "#48FF00",
+ type: "yes",
+ single: true,
+ nodeTypeNames: ["type2"]
+ });
+
+ handles.registerHandle({
+ positionX: "right",
+ positionY: "center",
+ color: "#ED1000",
+ type: "no",
+ single: true,
+ nodeTypeNames: ["type2"]
+ });
+
+
+ //ADD NODES
+ cy.add({
+ data: { id: 'n1', type: "type1"},
+ });
+
+ cy.add({
+ data: { id: 'n2', type: "type1"},
+ });
+
+ cy.add({
+ data: { id: 'n3', type: "type1"},
+ });
+
+ cy.add({
+ data: { id: 'n4', type: "type2"},
+ });
+
+
+ //ADJUST HEIGHT
+ var resizeViewport = function(){
+ $(".cy").height($(window).height());
+ cy.resize();
+ };
+
+ $(window).resize(resizeViewport);
+ resizeViewport();
+
+ //LAYOUT
+ cy.layout({
+ name: 'random',
+ fit: true,
+ padding: 40,
+ boundingBox: {x1: -200, y1:-200, x2:300, y2: 200}
+ });
+ });
+ </script>
+ <style>
+ * {
+ padding: 0;
+ margin: 0;
+ }
+ .cy {
+ width: 100%;
+ height:100%;
+ }
+ </style>
+</head>
+<body>
+ <div class="cy"></div>
+</body>
+</html> \ No newline at end of file