import cytoscape from 'cytoscape'; import $ from "jquery"; import 'jquery-ui-dist/jquery-ui'; import EditorActionsManager from "../managers/EditorActionsManager"; export default class DragDropNodeAddPlugin { pathwayHandler: (pathwayName: string) => void; private cy: any; private editor: EditorActionsManager; constructor(editor: EditorActionsManager, cy: any, pathwayHandler: (pathwayName: string) => void) { this.editor = editor; this.cy = cy; this.pathwayHandler = pathwayHandler; this.initNodeAdd(); } //TODO JQUERY IS IGNORED initNodeAdd() { var nodeAddClass = this; var defaults = { height: 30, //height of the icon container width: 30, //width of the icon container padding: 5, //padding of the icon container(from right & top) backgroundColorDiv: '#fbfbfb', //background color of the icon container borderColorDiv: '#fff', //border color of the icon container borderWidthDiv: '0px', //border width of the icon container borderRadiusDiv: '5px', //border radius of the icon container icon: '', //icon class name nodeParams: function(){ // return element object to be passed to cy.add() for adding node return {}; } }; const self = this; // @ts-ignore $.fn.cytoscapeNodeadd = function(params: any) { var options = $.extend(true, {}, defaults, params); var fn = params; var functions = { destroy: function() { var $this = $(this); $this.find(".ui-cytoscape-nodeadd").remove(); }, init: function() { return $(this).each(function() { var components = options.components; for (const component of components) { var dragContainer = component.container; //var explanationText = component.explanationText; var $nodeadd = $('
'); dragContainer.append($nodeadd); var $nodeDragHandle = $('
\ \ \ \
'); $nodeadd.append($nodeDragHandle); $nodeDragHandle.bind("mousedown", function(e: any) { e.stopPropagation(); // don't trigger dragging of nodeadd e.preventDefault(); // don't cause text selection }); //Setup UI dragContainer.find(".ui-cytoscape-nodeadd-nodediv").css({ background: options.backgroundColorDiv, border: options.borderWidthDiv + ' solid ' + options.borderColorDiv, 'border-radius': options.borderRadiusDiv }); //Init Draggable dragContainer.find("#ui-cytoscape-nodeadd-icon").draggable({ helper: "clone", cursor: "pointer" }); } // @ts-ignore TODO: AMENDMENT ATTENTION var $container = $(this); //Init Droppable // @ts-ignore TODO: Droppable is ignored $container.droppable({ activeClass: "ui-state-highlight", // accept: "#ui-cytoscape-nodeadd-icon", drop: function(event: any, ui: any) { $container.removeClass("ui-state-highlight"); var currentOffset = $container.offset(); var relX = event.pageX - currentOffset.left; var relY = event.pageY - currentOffset.top; var nodeType = $(ui.helper).attr('nodeType').toUpperCase(); var cy = nodeAddClass.cy; //Hold a map for parents and candidate parent nodes for this addition var nodeMap = {}; var parentMap = {}; //Loop through nodes for hit testing about drag position on canvas cy.nodes().forEach(function(node: any) { var nodeBbox = node.renderedBoundingBox(); //Rectangle point test if ( (relX <= nodeBbox.x2 && relX >= nodeBbox.x1) && (relY <= nodeBbox.y2 && relY >= nodeBbox.y1) && node.data().type != 'GENE' ) { //If node has a children put an entry to the parentMap if (node.children().length > 0) { parentMap[node.id()] = true; } //If parent of this node is already added to the node map remove it, since our candidate is in deeper level ! if (parentMap[node._private.data.parent]) { delete nodeMap[node._private.data.parent]; } //Add an entry to node map nodeMap[node.id()] = node; } }); //Check if any parent found, if so set parent field var parent = nodeMap[Object.keys(nodeMap)[0]]; var nodeData = {w: "0", h: "100", parent: 0, type: nodeType, name:'New '+ $(ui.helper).attr('nodeType')}; if (parent) { if(parent.data().type == "FAMILY" || parent.data().type == "COMPLEX") { if(nodeType != "COMPARTMENT" && nodeType != "PROCESS") { nodeData.parent = parent.id(); } } else { nodeData.parent = parent.id(); } } if (nodeType === "PROCESS") { nodeData.w = "100"; nodeData.h = "35"; } else { nodeData.w = "150"; nodeData.h = "52"; } //Adjust position according to the zoom level and pan ! //To set rendered position !!! //TODO refactor this ! relX = relX / cy.zoom() + cy.extent().x1; relY = relY / cy.zoom() + cy.extent().y1; nodeAddClass.editor.addNode(nodeData,{x: relX,y: relY}); self.pathwayHandler("Additional Pathway"); } }); }); } }; if (functions[fn]) { return functions[fn].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof fn == 'object' || !fn) { return functions.init.apply(this, arguments); } else { $.error("No such function `" + fn + "` for jquery.cytoscapenodeadd"); } return $(this); }; // @ts-ignore $.fn.cynodeadd = $.fn.cytoscapeNodeadd; try{ /* Adding as an extension to the core functionality of cytoscape.js*/ cytoscape('core', 'nodeadd', function(options: any) { // @ts-ignore $(this.container()).cytoscapeNodeadd(options); }); } catch(err){ console.log(err); } } }