diff options
Diffstat (limited to 'catalog-ui/non_bower_components')
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 |