mirror of https://github.com/MISP/MISP
2225 lines
92 KiB
JavaScript
2225 lines
92 KiB
JavaScript
class Drawflow {
|
|
constructor(container, render = null, parent = null) {
|
|
this.events = {};
|
|
this.container = container;
|
|
this.precanvas = null;
|
|
this.nodeId = 1;
|
|
this.ele_selected = null;
|
|
this.node_selected = null;
|
|
this.framenode_selected = null;
|
|
this.drag = false;
|
|
this.reroute = false;
|
|
this.reroute_fix_curvature = false;
|
|
this.curvature = 0.5;
|
|
this.reroute_curvature_start_end = 0.5;
|
|
this.reroute_curvature = 0.5;
|
|
this.reroute_width = 6;
|
|
this.drag_point = false;
|
|
this.editor_selected = false;
|
|
this.connection = false;
|
|
this.connection_ele = null;
|
|
this.connection_selected = null;
|
|
this.canvas_x = 0;
|
|
this.canvas_y = 0;
|
|
this.pos_x = 0;
|
|
this.pos_x_start = 0;
|
|
this.pos_y = 0;
|
|
this.pos_y_start = 0;
|
|
this.mouse_x = 0;
|
|
this.mouse_y = 0;
|
|
this.line_path = 5;
|
|
this.first_click = null;
|
|
this.force_first_input = false;
|
|
this.draggable_inputs = true;
|
|
this.useuuid = false;
|
|
this.parent = parent;
|
|
this.frame_to_nodes_registry = {};
|
|
this.nodes_to_frames_registry = {};
|
|
|
|
this.noderegister = {};
|
|
this.render = render;
|
|
this.drawflow = { "drawflow": { "Home": { "data": { "_frames": {} } } } };
|
|
// Configurable options
|
|
this.module = 'Home';
|
|
this.editor_mode = 'edit';
|
|
this.zoom = 1;
|
|
this.zoom_max = 1.6;
|
|
this.zoom_min = 0.5;
|
|
this.zoom_value = 0.1;
|
|
this.zoom_last_value = 1;
|
|
this.frameNodePadding = { "top": 100, "left": 30, "right": 30, "bottom": 20 }
|
|
|
|
// Mobile
|
|
this.evCache = new Array();
|
|
this.prevDiff = -1;
|
|
}
|
|
|
|
start() {
|
|
// console.info("Start Drawflow!!");
|
|
this.container.classList.add("parent-drawflow");
|
|
this.container.tabIndex = 0;
|
|
this.precanvas = document.createElement('div');
|
|
this.precanvas.classList.add("drawflow");
|
|
this.container.appendChild(this.precanvas);
|
|
|
|
/* Mouse and Touch Actions */
|
|
this.container.addEventListener('mouseup', this.dragEnd.bind(this));
|
|
this.container.addEventListener('mousemove', this.position.bind(this));
|
|
this.container.addEventListener('mousedown', this.click.bind(this));
|
|
|
|
this.container.addEventListener('touchend', this.dragEnd.bind(this));
|
|
this.container.addEventListener('touchmove', this.position.bind(this));
|
|
this.container.addEventListener('touchstart', this.click.bind(this));
|
|
|
|
/* Context Menu */
|
|
this.container.addEventListener('contextmenu', this.contextmenu.bind(this));
|
|
/* Delete */
|
|
this.container.addEventListener('keydown', this.key.bind(this));
|
|
|
|
/* Zoom Mouse */
|
|
this.container.addEventListener('wheel', this.zoom_enter.bind(this));
|
|
/* Update data Nodes */
|
|
this.container.addEventListener('input', this.updateNodeValue.bind(this));
|
|
|
|
this.container.addEventListener('dblclick', this.dblclick.bind(this));
|
|
/* Mobile zoom */
|
|
this.container.onpointerdown = this.pointerdown_handler.bind(this);
|
|
this.container.onpointermove = this.pointermove_handler.bind(this);
|
|
this.container.onpointerup = this.pointerup_handler.bind(this);
|
|
this.container.onpointercancel = this.pointerup_handler.bind(this);
|
|
this.container.onpointerout = this.pointerup_handler.bind(this);
|
|
this.container.onpointerleave = this.pointerup_handler.bind(this);
|
|
|
|
this.load();
|
|
}
|
|
|
|
/* Mobile zoom */
|
|
pointerdown_handler(ev) {
|
|
this.evCache.push(ev);
|
|
}
|
|
|
|
pointermove_handler(ev) {
|
|
for (var i = 0; i < this.evCache.length; i++) {
|
|
if (ev.pointerId == this.evCache[i].pointerId) {
|
|
this.evCache[i] = ev;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (this.evCache.length == 2) {
|
|
// Calculate the distance between the two pointers
|
|
var curDiff = Math.abs(this.evCache[0].clientX - this.evCache[1].clientX);
|
|
|
|
if (this.prevDiff > 100) {
|
|
if (curDiff > this.prevDiff) {
|
|
// The distance between the two pointers has increased
|
|
|
|
this.zoom_in();
|
|
}
|
|
if (curDiff < this.prevDiff) {
|
|
// The distance between the two pointers has decreased
|
|
this.zoom_out();
|
|
}
|
|
}
|
|
this.prevDiff = curDiff;
|
|
}
|
|
}
|
|
|
|
pointerup_handler(ev) {
|
|
this.remove_event(ev);
|
|
if (this.evCache.length < 2) {
|
|
this.prevDiff = -1;
|
|
}
|
|
}
|
|
remove_event(ev) {
|
|
// Remove this event from the target's cache
|
|
for (var i = 0; i < this.evCache.length; i++) {
|
|
if (this.evCache[i].pointerId == ev.pointerId) {
|
|
this.evCache.splice(i, 1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* End Mobile Zoom */
|
|
load() {
|
|
for (var key in this.drawflow.drawflow[this.module].data) {
|
|
if (!key.startsWith('_')) {
|
|
this.addNodeImport(this.drawflow.drawflow[this.module].data[key], this.precanvas);
|
|
}
|
|
}
|
|
|
|
if (this.reroute) {
|
|
for (var key in this.drawflow.drawflow[this.module].data) {
|
|
this.addRerouteImport(this.drawflow.drawflow[this.module].data[key]);
|
|
}
|
|
}
|
|
|
|
for (var key in this.drawflow.drawflow[this.module].data) {
|
|
this.updateConnectionNodes('node-' + key);
|
|
}
|
|
|
|
const editor = this.drawflow.drawflow;
|
|
let number = 1;
|
|
Object.keys(editor).map(function (moduleName, index) {
|
|
Object.keys(editor[moduleName].data).map(function (id, index2) {
|
|
if (parseInt(id) >= number) {
|
|
number = parseInt(id) + 1;
|
|
}
|
|
});
|
|
});
|
|
this.nodeId = number;
|
|
}
|
|
|
|
removeReouteConnectionSelected() {
|
|
this.dispatch('connectionUnselected', true);
|
|
if (this.reroute_fix_curvature) {
|
|
this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((item, i) => {
|
|
item.classList.remove("selected");
|
|
});
|
|
}
|
|
}
|
|
|
|
click(e) {
|
|
this.dispatch('click', e);
|
|
if (this.editor_mode === 'fixed') {
|
|
//return false;
|
|
e.preventDefault();
|
|
if (e.target.classList[0] === 'parent-drawflow' || e.target.classList[0] === 'drawflow') {
|
|
this.ele_selected = e.target.closest(".parent-drawflow");
|
|
} else {
|
|
return false;
|
|
}
|
|
} else if (this.editor_mode === 'view') {
|
|
if (e.target.closest(".drawflow") != null || e.target.matches('.parent-drawflow')) {
|
|
this.ele_selected = e.target.closest(".parent-drawflow");
|
|
e.preventDefault();
|
|
}
|
|
} else {
|
|
this.first_click = e.target;
|
|
this.ele_selected = e.target;
|
|
if (e.button === 0) {
|
|
this.contextmenuDel();
|
|
}
|
|
|
|
if (e.target.closest(".drawflow_content_node") != null) {
|
|
this.ele_selected = e.target.closest(".drawflow_content_node").parentElement;
|
|
}
|
|
}
|
|
switch (this.ele_selected.classList[0]) {
|
|
case 'drawflow-node':
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
if (this.node_selected != this.ele_selected) {
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
if (this.node_selected != this.ele_selected) {
|
|
this.dispatch('nodeSelected', this.ele_selected.id.slice(5));
|
|
}
|
|
this.node_selected = this.ele_selected;
|
|
this.node_selected.classList.add("selected");
|
|
if (!this.draggable_inputs) {
|
|
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT' && e.target.hasAttribute('contenteditable') !== true) {
|
|
this.drag = true;
|
|
}
|
|
} else {
|
|
if (e.target.tagName !== 'SELECT') {
|
|
this.drag = true;
|
|
}
|
|
}
|
|
break;
|
|
case 'output':
|
|
this.connection = true;
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null;
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
this.drawConnection(e.target);
|
|
break;
|
|
case 'drawflow-framenode':
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
this.framenode_selected = this.ele_selected;
|
|
this.framenode_selected.classList.add("selected");
|
|
break;
|
|
case 'parent-drawflow':
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null;
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
this.editor_selected = true;
|
|
break;
|
|
case 'drawflow':
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null;
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
this.editor_selected = true;
|
|
break;
|
|
case 'main-path':
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null;
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
this.connection_selected = this.ele_selected;
|
|
this.connection_selected.classList.add("selected");
|
|
const listclassConnection = this.connection_selected.parentElement.classList;
|
|
if (listclassConnection.length > 1) {
|
|
this.dispatch('connectionSelected', { output_id: listclassConnection[2].slice(14), input_id: listclassConnection[1].slice(13), output_class: listclassConnection[3], input_class: listclassConnection[4] });
|
|
if (this.reroute_fix_curvature) {
|
|
this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((item, i) => {
|
|
item.classList.add("selected");
|
|
});
|
|
}
|
|
}
|
|
break;
|
|
case 'point':
|
|
this.drag_point = true;
|
|
this.ele_selected.classList.add("selected");
|
|
break;
|
|
case 'drawflow-delete':
|
|
if (this.node_selected) {
|
|
this.removeNodeId(this.node_selected.id);
|
|
}
|
|
|
|
if (this.connection_selected) {
|
|
this.removeConnection();
|
|
}
|
|
|
|
if (this.framenode_selected) {
|
|
this.removeFrameNodeId(this.framenode_selected.id);
|
|
}
|
|
|
|
if (this.node_selected != null) {
|
|
this.node_selected.classList.remove("selected");
|
|
this.node_selected = null;
|
|
this.dispatch('nodeUnselected', true);
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.connection_selected.classList.remove("selected");
|
|
this.removeReouteConnectionSelected();
|
|
this.connection_selected = null;
|
|
}
|
|
if (this.framenode_selected != null) {
|
|
this.framenode_selected.classList.remove("selected");
|
|
this.framenode_selected = null
|
|
}
|
|
|
|
break;
|
|
default:
|
|
}
|
|
if (e.type === "touchstart") {
|
|
this.pos_x = e.touches[0].clientX;
|
|
this.pos_x_start = e.touches[0].clientX;
|
|
this.pos_y = e.touches[0].clientY;
|
|
this.pos_y_start = e.touches[0].clientY;
|
|
this.mouse_x = e.touches[0].clientX;
|
|
this.mouse_y = e.touches[0].clientY;
|
|
} else {
|
|
this.pos_x = e.clientX;
|
|
this.pos_x_start = e.clientX;
|
|
this.pos_y = e.clientY;
|
|
this.pos_y_start = e.clientY;
|
|
}
|
|
if (['input', 'output', 'main-path'].includes(this.ele_selected.classList[0])) {
|
|
e.preventDefault();
|
|
}
|
|
this.dispatch('clickEnd', e);
|
|
}
|
|
|
|
position(e) {
|
|
if (e.type === "touchmove") {
|
|
var e_pos_x = e.touches[0].clientX;
|
|
var e_pos_y = e.touches[0].clientY;
|
|
} else {
|
|
var e_pos_x = e.clientX;
|
|
var e_pos_y = e.clientY;
|
|
}
|
|
|
|
|
|
if (this.connection) {
|
|
this.updateConnection(e_pos_x, e_pos_y);
|
|
}
|
|
if (this.editor_selected) {
|
|
x = this.canvas_x + (-(this.pos_x - e_pos_x))
|
|
y = this.canvas_y + (-(this.pos_y - e_pos_y))
|
|
this.dispatch('translate', { x: x, y: y });
|
|
this.precanvas.style.transform = "translate(" + x + "px, " + y + "px) scale(" + this.zoom + ")";
|
|
}
|
|
if (this.drag) {
|
|
e.preventDefault();
|
|
var x = (this.pos_x - e_pos_x) * this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom);
|
|
var y = (this.pos_y - e_pos_y) * this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom);
|
|
this.pos_x = e_pos_x;
|
|
this.pos_y = e_pos_y;
|
|
|
|
this.ele_selected.style.top = (this.ele_selected.offsetTop - y) + "px";
|
|
this.ele_selected.style.left = (this.ele_selected.offsetLeft - x) + "px";
|
|
|
|
this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_x = (this.ele_selected.offsetLeft - x);
|
|
this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_y = (this.ele_selected.offsetTop - y);
|
|
|
|
this.updateConnectionNodes(this.ele_selected.id)
|
|
}
|
|
|
|
if (this.drag_point) {
|
|
|
|
var x = (this.pos_x - e_pos_x) * this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom);
|
|
var y = (this.pos_y - e_pos_y) * this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom);
|
|
this.pos_x = e_pos_x;
|
|
this.pos_y = e_pos_y;
|
|
|
|
var pos_x = this.pos_x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)));
|
|
var pos_y = this.pos_y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)));
|
|
|
|
this.ele_selected.setAttributeNS(null, 'cx', pos_x);
|
|
this.ele_selected.setAttributeNS(null, 'cy', pos_y);
|
|
|
|
const nodeUpdate = this.ele_selected.parentElement.classList[2].slice(9);
|
|
const nodeUpdateIn = this.ele_selected.parentElement.classList[1].slice(13);
|
|
const output_class = this.ele_selected.parentElement.classList[3];
|
|
const input_class = this.ele_selected.parentElement.classList[4];
|
|
|
|
let numberPointPosition = Array.from(this.ele_selected.parentElement.children).indexOf(this.ele_selected) - 1;
|
|
|
|
if (this.reroute_fix_curvature) {
|
|
const numberMainPath = this.ele_selected.parentElement.querySelectorAll(".main-path").length - 1;
|
|
numberPointPosition -= numberMainPath;
|
|
if (numberPointPosition < 0) {
|
|
numberPointPosition = 0;
|
|
}
|
|
}
|
|
|
|
const nodeId = nodeUpdate.slice(5);
|
|
const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function (item, i) {
|
|
return item.node === nodeUpdateIn && item.output === input_class;
|
|
});
|
|
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points[numberPointPosition] = { pos_x: pos_x, pos_y: pos_y };
|
|
|
|
const parentSelected = this.ele_selected.parentElement.classList[2].slice(9);
|
|
|
|
this.updateConnectionNodes(parentSelected);
|
|
}
|
|
|
|
if (e.type === "touchmove") {
|
|
this.mouse_x = e_pos_x;
|
|
this.mouse_y = e_pos_y;
|
|
}
|
|
this.dispatch('mouseMove', { x: e_pos_x, y: e_pos_y });
|
|
}
|
|
|
|
dragEnd(e) {
|
|
if (e.type === "touchend") {
|
|
var e_pos_x = this.mouse_x;
|
|
var e_pos_y = this.mouse_y;
|
|
var ele_last = document.elementFromPoint(e_pos_x, e_pos_y);
|
|
} else {
|
|
var e_pos_x = e.clientX;
|
|
var e_pos_y = e.clientY;
|
|
var ele_last = e.target;
|
|
}
|
|
|
|
if (this.drag) {
|
|
if (this.pos_x_start != e_pos_x || this.pos_y_start != e_pos_y) {
|
|
this.dispatch('nodeMoved', this.ele_selected.id.slice(5));
|
|
}
|
|
}
|
|
|
|
if (this.drag_point) {
|
|
this.ele_selected.classList.remove("selected");
|
|
if (this.pos_x_start != e_pos_x || this.pos_y_start != e_pos_y) {
|
|
this.dispatch('rerouteMoved', this.ele_selected.parentElement.classList[2].slice(14));
|
|
}
|
|
}
|
|
|
|
if (this.editor_selected) {
|
|
this.canvas_x = this.canvas_x + (-(this.pos_x - e_pos_x));
|
|
this.canvas_y = this.canvas_y + (-(this.pos_y - e_pos_y));
|
|
this.editor_selected = false;
|
|
}
|
|
if (this.connection === true) {
|
|
if (ele_last.classList[0] === 'input' || (this.force_first_input && (ele_last.closest(".drawflow_content_node") != null || ele_last.classList[0] === 'drawflow-node'))) {
|
|
|
|
if (this.force_first_input && (ele_last.closest(".drawflow_content_node") != null || ele_last.classList[0] === 'drawflow-node')) {
|
|
if (ele_last.closest(".drawflow_content_node") != null) {
|
|
var input_id = ele_last.closest(".drawflow_content_node").parentElement.id;
|
|
} else {
|
|
var input_id = ele_last.id;
|
|
}
|
|
if (Object.keys(this.getNodeFromId(input_id.slice(5)).inputs).length === 0) {
|
|
var input_class = false;
|
|
} else {
|
|
var input_class = "input_1";
|
|
}
|
|
|
|
|
|
} else {
|
|
// Fix connection;
|
|
var input_id = ele_last.parentElement.parentElement.id;
|
|
var input_class = ele_last.classList[1];
|
|
}
|
|
var output_id = this.ele_selected.parentElement.parentElement.id;
|
|
var output_class = this.ele_selected.classList[1];
|
|
|
|
if (output_id !== input_id && input_class !== false) {
|
|
|
|
if (this.container.querySelectorAll('.connection.node_in_' + input_id + '.node_out_' + output_id + '.' + output_class + '.' + input_class).length === 0) {
|
|
// Conection no exist save connection
|
|
|
|
this.connection_ele.classList.add("node_in_" + input_id);
|
|
this.connection_ele.classList.add("node_out_" + output_id);
|
|
this.connection_ele.classList.add(output_class);
|
|
this.connection_ele.classList.add(input_class);
|
|
var id_input = input_id.slice(5);
|
|
var id_output = output_id.slice(5);
|
|
|
|
this.drawflow.drawflow[this.module].data[id_output].outputs[output_class].connections.push({ "node": id_input, "output": input_class });
|
|
this.drawflow.drawflow[this.module].data[id_input].inputs[input_class].connections.push({ "node": id_output, "input": output_class });
|
|
this.updateConnectionNodes('node-' + id_output);
|
|
this.updateConnectionNodes('node-' + id_input);
|
|
this.dispatch('connectionCreated', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class });
|
|
|
|
} else {
|
|
this.dispatch('connectionCancel', true);
|
|
this.connection_ele.remove();
|
|
}
|
|
|
|
this.connection_ele = null;
|
|
} else {
|
|
// Connection exists Remove Connection;
|
|
this.dispatch('connectionCancel', true);
|
|
this.connection_ele.remove();
|
|
this.connection_ele = null;
|
|
}
|
|
|
|
} else {
|
|
// Remove Connection;
|
|
this.dispatch('connectionCancel', true);
|
|
this.connection_ele.remove();
|
|
this.connection_ele = null;
|
|
}
|
|
}
|
|
|
|
this.drag = false;
|
|
this.drag_point = false;
|
|
this.connection = false;
|
|
this.ele_selected = null;
|
|
this.editor_selected = false;
|
|
|
|
this.dispatch('mouseUp', e);
|
|
}
|
|
contextmenu(e) {
|
|
this.dispatch('contextmenu', e);
|
|
e.preventDefault();
|
|
if (this.editor_mode === 'fixed' || this.editor_mode === 'view') {
|
|
return false;
|
|
}
|
|
if (this.precanvas.getElementsByClassName("drawflow-delete").length) {
|
|
this.precanvas.getElementsByClassName("drawflow-delete")[0].remove()
|
|
};
|
|
if (this.node_selected || this.connection_selected) {
|
|
var deletebox = document.createElement('div');
|
|
deletebox.classList.add("drawflow-delete");
|
|
deletebox.innerHTML = "x";
|
|
if (this.node_selected) {
|
|
this.node_selected.appendChild(deletebox);
|
|
|
|
}
|
|
if (this.connection_selected && (this.connection_selected.parentElement.classList.length > 1)) {
|
|
deletebox.style.top = e.clientY * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom))) + "px";
|
|
deletebox.style.left = e.clientX * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom))) + "px";
|
|
|
|
this.precanvas.appendChild(deletebox);
|
|
|
|
}
|
|
|
|
} else {
|
|
if (e.target.classList.contains('drawflow-framenode') || e.target.classList.contains('drawflow-framenode-text')) {
|
|
const frameNode = e.target.classList.contains('drawflow-framenode') ? e.target : e.target.parentElement
|
|
const deletebox = document.createElement('div');
|
|
deletebox.classList.add("drawflow-delete");
|
|
deletebox.innerHTML = "x";
|
|
|
|
const frameNodeBCR = frameNode.getBoundingClientRect()
|
|
const pos_y = frameNodeBCR.top - 30 // roughly include margin and node size
|
|
const pos_x = frameNodeBCR.left + frameNodeBCR.width
|
|
deletebox.style.top = pos_y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom))) + "px";
|
|
deletebox.style.left = pos_x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom))) + "px";
|
|
|
|
this.precanvas.appendChild(deletebox);
|
|
}
|
|
}
|
|
|
|
}
|
|
contextmenuDel() {
|
|
if (this.precanvas.getElementsByClassName("drawflow-delete").length) {
|
|
this.precanvas.getElementsByClassName("drawflow-delete")[0].remove()
|
|
};
|
|
}
|
|
|
|
key(e) {
|
|
this.dispatch('keydown', e);
|
|
if (this.editor_mode === 'fixed' || this.editor_mode === 'view') {
|
|
return false;
|
|
}
|
|
if (e.key === 'Delete' || (e.key === 'Backspace' && e.metaKey)) {
|
|
if (this.node_selected != null) {
|
|
if (this.first_click.tagName !== 'INPUT' && this.first_click.tagName !== 'TEXTAREA' && this.first_click.hasAttribute('contenteditable') !== true) {
|
|
this.removeNodeId(this.node_selected.id);
|
|
}
|
|
}
|
|
if (this.connection_selected != null) {
|
|
this.removeConnection();
|
|
}
|
|
}
|
|
}
|
|
|
|
zoom_enter(event, delta) {
|
|
if (event.ctrlKey) {
|
|
event.preventDefault()
|
|
if (event.deltaY > 0) {
|
|
// Zoom Out
|
|
this.zoom_out();
|
|
} else {
|
|
// Zoom In
|
|
this.zoom_in();
|
|
}
|
|
}
|
|
}
|
|
zoom_refresh() {
|
|
this.dispatch('zoom', this.zoom);
|
|
this.canvas_x = (this.canvas_x / this.zoom_last_value) * this.zoom;
|
|
this.canvas_y = (this.canvas_y / this.zoom_last_value) * this.zoom;
|
|
this.zoom_last_value = this.zoom;
|
|
this.precanvas.style.transform = "translate(" + this.canvas_x + "px, " + this.canvas_y + "px) scale(" + this.zoom + ")";
|
|
}
|
|
zoom_in() {
|
|
if (this.zoom < this.zoom_max) {
|
|
this.zoom += this.zoom_value;
|
|
this.zoom_refresh();
|
|
}
|
|
}
|
|
zoom_out() {
|
|
if (this.zoom > this.zoom_min) {
|
|
this.zoom -= this.zoom_value;
|
|
this.zoom_refresh();
|
|
}
|
|
}
|
|
zoom_reset() {
|
|
if (this.zoom != 1) {
|
|
this.zoom = 1;
|
|
this.zoom_refresh();
|
|
}
|
|
}
|
|
|
|
createCurvature(start_pos_x, start_pos_y, end_pos_x, end_pos_y, curvature_value, type) {
|
|
var line_x = start_pos_x;
|
|
var line_y = start_pos_y;
|
|
var x = end_pos_x;
|
|
var y = end_pos_y;
|
|
var curvature = curvature_value;
|
|
//type openclose open close other
|
|
switch (type) {
|
|
case 'open':
|
|
if (start_pos_x >= end_pos_x) {
|
|
var hx1 = line_x + Math.abs(x - line_x) * curvature;
|
|
var hx2 = x - Math.abs(x - line_x) * (curvature * -1);
|
|
} else {
|
|
var hx1 = line_x + Math.abs(x - line_x) * curvature;
|
|
var hx2 = x - Math.abs(x - line_x) * curvature;
|
|
}
|
|
return ' M ' + line_x + ' ' + line_y + ' C ' + hx1 + ' ' + line_y + ' ' + hx2 + ' ' + y + ' ' + x + ' ' + y;
|
|
|
|
break
|
|
case 'close':
|
|
if (start_pos_x >= end_pos_x) {
|
|
var hx1 = line_x + Math.abs(x - line_x) * (curvature * -1);
|
|
var hx2 = x - Math.abs(x - line_x) * curvature;
|
|
} else {
|
|
var hx1 = line_x + Math.abs(x - line_x) * curvature;
|
|
var hx2 = x - Math.abs(x - line_x) * curvature;
|
|
}
|
|
return ' M ' + line_x + ' ' + line_y + ' C ' + hx1 + ' ' + line_y + ' ' + hx2 + ' ' + y + ' ' + x + ' ' + y;
|
|
break;
|
|
case 'other':
|
|
if (start_pos_x >= end_pos_x) {
|
|
var hx1 = line_x + Math.abs(x - line_x) * (curvature * -1);
|
|
var hx2 = x - Math.abs(x - line_x) * (curvature * -1);
|
|
} else {
|
|
var hx1 = line_x + Math.abs(x - line_x) * curvature;
|
|
var hx2 = x - Math.abs(x - line_x) * curvature;
|
|
}
|
|
return ' M ' + line_x + ' ' + line_y + ' C ' + hx1 + ' ' + line_y + ' ' + hx2 + ' ' + y + ' ' + x + ' ' + y;
|
|
break;
|
|
default:
|
|
|
|
var hx1 = line_x + Math.abs(x - line_x) * curvature;
|
|
var hx2 = x - Math.abs(x - line_x) * curvature;
|
|
|
|
return ' M ' + line_x + ' ' + line_y + ' C ' + hx1 + ' ' + line_y + ' ' + hx2 + ' ' + y + ' ' + x + ' ' + y;
|
|
}
|
|
|
|
}
|
|
|
|
drawConnection(ele) {
|
|
var connection = document.createElementNS('http://www.w3.org/2000/svg', "svg");
|
|
this.connection_ele = connection;
|
|
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
|
|
path.classList.add("main-path");
|
|
path.setAttributeNS(null, 'd', '');
|
|
// path.innerHTML = 'a';
|
|
connection.classList.add("connection");
|
|
connection.appendChild(path);
|
|
this.precanvas.appendChild(connection);
|
|
var id_output = ele.parentElement.parentElement.id.slice(5);
|
|
var output_class = ele.classList[1];
|
|
this.dispatch('connectionStart', { output_id: id_output, output_class: output_class });
|
|
|
|
}
|
|
|
|
updateConnection(eX, eY) {
|
|
const precanvas = this.precanvas;
|
|
const zoom = this.zoom;
|
|
let precanvasWitdhZoom = precanvas.clientWidth / (precanvas.clientWidth * zoom);
|
|
precanvasWitdhZoom = precanvasWitdhZoom || 0;
|
|
let precanvasHeightZoom = precanvas.clientHeight / (precanvas.clientHeight * zoom);
|
|
precanvasHeightZoom = precanvasHeightZoom || 0;
|
|
var path = this.connection_ele.children[0];
|
|
|
|
var line_x = this.ele_selected.offsetWidth / 2 + (this.ele_selected.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = this.ele_selected.offsetHeight / 2 + (this.ele_selected.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var x = eX * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)));
|
|
var y = eY * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)));
|
|
|
|
var curvature = this.curvature;
|
|
var lineCurve = this.createCurvature(line_x, line_y, x, y, curvature, 'openclose');
|
|
path.setAttributeNS(null, 'd', lineCurve);
|
|
|
|
}
|
|
|
|
addConnection(id_output, id_input, output_class, input_class, labels) {
|
|
var nodeOneModule = this.getModuleFromNodeId(id_output);
|
|
var nodeTwoModule = this.getModuleFromNodeId(id_input);
|
|
if (nodeOneModule === nodeTwoModule) {
|
|
|
|
var dataNode = this.getNodeFromId(id_output);
|
|
var exist = false;
|
|
for (var checkOutput in dataNode.outputs[output_class].connections) {
|
|
var connectionSearch = dataNode.outputs[output_class].connections[checkOutput]
|
|
if (connectionSearch.node == id_input && connectionSearch.output == input_class) {
|
|
exist = true;
|
|
}
|
|
}
|
|
// Check connection exist
|
|
if (exist === false) {
|
|
//Create Connection
|
|
this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.push({ "node": id_input.toString(), "output": input_class });
|
|
this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.push({ "node": id_output.toString(), "input": output_class });
|
|
|
|
if (this.module === nodeOneModule) {
|
|
//Draw connection
|
|
var connection = document.createElementNS('http://www.w3.org/2000/svg', "svg");
|
|
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
|
|
path.classList.add("main-path");
|
|
path.setAttributeNS(null, 'd', '');
|
|
// path.innerHTML = 'a';
|
|
connection.classList.add("connection");
|
|
connection.classList.add("node_in_node-" + id_input);
|
|
connection.classList.add("node_out_node-" + id_output);
|
|
connection.classList.add(output_class);
|
|
connection.classList.add(input_class);
|
|
connection.appendChild(path);
|
|
if (labels) {
|
|
var connectionLabel = this.buildConnectionLabels(labels, id_input, id_output)
|
|
connection.appendChild(connectionLabel);
|
|
}
|
|
this.precanvas.appendChild(connection);
|
|
this.updateConnectionNodes('node-' + id_output);
|
|
this.updateConnectionNodes('node-' + id_input);
|
|
}
|
|
|
|
this.dispatch('connectionCreated', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class });
|
|
}
|
|
}
|
|
}
|
|
|
|
buildConnectionLabels(labels, id_input, id_output) {
|
|
var foreignObject = document.createElementNS('http://www.w3.org/2000/svg', "foreignObject");
|
|
if (!labels || labels.length == 0) {
|
|
return foreignObject;
|
|
}
|
|
foreignObject.setAttributeNS(null, 'width', '100%');
|
|
foreignObject.setAttributeNS(null, 'height', '100%');
|
|
foreignObject.style['overflow'] = 'visible';
|
|
var div = document.createElement('div');
|
|
labels.forEach((labelHtml) => {
|
|
var template = document.createElement('template');
|
|
labelHtml = labelHtml.trim();
|
|
template.innerHTML = labelHtml;
|
|
div.appendChild(template.content.firstChild);
|
|
})
|
|
div.classList.add("connection-label-container");
|
|
div.setAttribute('node_in', id_input);
|
|
div.setAttribute('node_out', id_output);
|
|
foreignObject.appendChild(div);
|
|
return foreignObject;
|
|
}
|
|
|
|
updateConnectionLabels(labelFOContainer, start_pos_x, start_pos_y, end_pos_x, end_pos_y) {
|
|
var xMid = start_pos_x + (end_pos_x - start_pos_x) / 2
|
|
var yMid = start_pos_y + (end_pos_y - start_pos_y) / 2
|
|
labelFOContainer.setAttributeNS(null, 'x', xMid);
|
|
labelFOContainer.setAttributeNS(null, 'y', yMid);
|
|
}
|
|
|
|
updateConnectionNodes(id) {
|
|
|
|
// Aquí nos quedamos;
|
|
const idSearch = 'node_in_' + id;
|
|
const idSearchOut = 'node_out_' + id;
|
|
var line_path = this.line_path / 2;
|
|
const container = this.container;
|
|
const precanvas = this.precanvas;
|
|
const curvature = this.curvature;
|
|
const createCurvature = this.createCurvature;
|
|
const updateConnectionLabels = this.updateConnectionLabels;
|
|
const reroute_curvature = this.reroute_curvature;
|
|
const reroute_curvature_start_end = this.reroute_curvature_start_end;
|
|
const reroute_fix_curvature = this.reroute_fix_curvature;
|
|
const rerouteWidth = this.reroute_width;
|
|
const zoom = this.zoom;
|
|
let precanvasWitdhZoom = precanvas.clientWidth / (precanvas.clientWidth * zoom);
|
|
precanvasWitdhZoom = precanvasWitdhZoom || 0;
|
|
let precanvasHeightZoom = precanvas.clientHeight / (precanvas.clientHeight * zoom);
|
|
precanvasHeightZoom = precanvasHeightZoom || 0;
|
|
|
|
const elemsOut = container.querySelectorAll(`.${idSearchOut}`);
|
|
|
|
Object.keys(elemsOut).map(function (item, index) {
|
|
if (elemsOut[item].querySelector('.point') === null) {
|
|
|
|
var elemtsearchId_out = container.querySelector(`#${id}`);
|
|
|
|
var id_search = elemsOut[item].classList[1].replace('node_in_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + elemsOut[item].classList[4])[0]
|
|
|
|
var eX = elemtsearch.offsetWidth / 2 + (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var eY = elemtsearch.offsetHeight / 2 + (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var elemtsearchOut = elemtsearchId_out.querySelectorAll('.' + elemsOut[item].classList[3])[0]
|
|
|
|
var line_x = elemtsearchOut.offsetWidth / 2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearchOut.offsetHeight / 2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
const lineCurve = createCurvature(line_x, line_y, x, y, curvature, 'openclose');
|
|
elemsOut[item].children[0].setAttributeNS(null, 'd', lineCurve);
|
|
if (elemsOut[item].children[1]) {
|
|
updateConnectionLabels(elemsOut[item].children[1], line_x, line_y, x, y);
|
|
}
|
|
} else {
|
|
const points = elemsOut[item].querySelectorAll('.point');
|
|
let linecurve = '';
|
|
const reoute_fix = [];
|
|
points.forEach((item, i) => {
|
|
if (i === 0 && ((points.length - 1) === 0)) {
|
|
|
|
var elemtsearchId_out = container.querySelector(`#${id}`);
|
|
var elemtsearch = item;
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
|
|
var elemtsearchOut = elemtsearchId_out.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
var line_x = elemtsearchOut.offsetWidth / 2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearchOut.offsetHeight / 2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
var elemtsearchId_out = item;
|
|
var id_search = item.parentElement.classList[1].replace('node_in_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
|
|
var elemtsearchIn = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
var eX = elemtsearchIn.offsetWidth / 2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var eY = elemtsearchIn.offsetHeight / 2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
} else if (i === 0) {
|
|
|
|
var elemtsearchId_out = container.querySelector(`#${id}`);
|
|
var elemtsearch = item;
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
|
|
var elemtsearchOut = elemtsearchId_out.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
var line_x = elemtsearchOut.offsetWidth / 2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearchOut.offsetHeight / 2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
// SECOND
|
|
var elemtsearchId_out = item;
|
|
var elemtsearch = points[i + 1];
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
} else if (i === (points.length - 1)) {
|
|
|
|
var elemtsearchId_out = item;
|
|
|
|
var id_search = item.parentElement.classList[1].replace('node_in_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
|
|
var elemtsearchIn = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
var eX = elemtsearchIn.offsetWidth / 2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var eY = elemtsearchIn.offsetHeight / 2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
} else {
|
|
var elemtsearchId_out = item;
|
|
var elemtsearch = points[i + 1];
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) + rerouteWidth;
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
}
|
|
|
|
});
|
|
if (reroute_fix_curvature) {
|
|
reoute_fix.forEach((itempath, i) => {
|
|
elemsOut[item].children[i].setAttributeNS(null, 'd', itempath);
|
|
});
|
|
|
|
} else {
|
|
elemsOut[item].children[0].setAttributeNS(null, 'd', linecurve);
|
|
}
|
|
|
|
}
|
|
})
|
|
|
|
const elems = container.querySelectorAll(`.${idSearch}`);
|
|
Object.keys(elems).map(function (item, index) {
|
|
|
|
if (elems[item].querySelector('.point') === null) {
|
|
var elemtsearchId_in = container.querySelector(`#${id}`);
|
|
|
|
var id_search = elems[item].classList[2].replace('node_out_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + elems[item].classList[3])[0]
|
|
|
|
var line_x = elemtsearch.offsetWidth / 2 + (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearch.offsetHeight / 2 + (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var elemtsearchId_in = elemtsearchId_in.querySelectorAll('.' + elems[item].classList[4])[0]
|
|
var x = elemtsearchId_in.offsetWidth / 2 + (elemtsearchId_in.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var y = elemtsearchId_in.offsetHeight / 2 + (elemtsearchId_in.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
const lineCurve = createCurvature(line_x, line_y, x, y, curvature, 'openclose');
|
|
elems[item].children[0].setAttributeNS(null, 'd', lineCurve);
|
|
if (elems[item].children[1]) {
|
|
updateConnectionLabels(elems[item].children[1], line_x, line_y, x, y);
|
|
}
|
|
|
|
} else {
|
|
const points = elems[item].querySelectorAll('.point');
|
|
let linecurve = '';
|
|
const reoute_fix = [];
|
|
points.forEach((item, i) => {
|
|
if (i === 0 && ((points.length - 1) === 0)) {
|
|
|
|
var elemtsearchId_out = container.querySelector(`#${id}`);
|
|
var elemtsearch = item;
|
|
|
|
var line_x = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
|
|
var elemtsearchIn = elemtsearchId_out.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
var eX = elemtsearchIn.offsetWidth / 2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var eY = elemtsearchIn.offsetHeight / 2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
var elemtsearchId_out = item;
|
|
var id_search = item.parentElement.classList[2].replace('node_out_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
|
|
var elemtsearchOut = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
var line_x = elemtsearchOut.offsetWidth / 2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearchOut.offsetHeight / 2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var eX = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
|
|
} else if (i === 0) {
|
|
// FIRST
|
|
var elemtsearchId_out = item;
|
|
var id_search = item.parentElement.classList[2].replace('node_out_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
var elemtsearchOut = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[3])[0]
|
|
var line_x = elemtsearchOut.offsetWidth / 2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var line_y = elemtsearchOut.offsetHeight / 2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var eX = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
// SECOND
|
|
var elemtsearchId_out = item;
|
|
var elemtsearch = points[i + 1];
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
} else if (i === (points.length - 1)) {
|
|
|
|
var elemtsearchId_out = item;
|
|
|
|
var id_search = item.parentElement.classList[1].replace('node_in_', '');
|
|
var elemtsearchId = container.querySelector(`#${id_search}`);
|
|
var elemtsearch = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
|
|
var elemtsearchIn = elemtsearchId.querySelectorAll('.' + item.parentElement.classList[4])[0]
|
|
var eX = elemtsearchIn.offsetWidth / 2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom;
|
|
var eY = elemtsearchIn.offsetHeight / 2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom;
|
|
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
|
|
} else {
|
|
|
|
var elemtsearchId_out = item;
|
|
var elemtsearch = points[i + 1];
|
|
|
|
var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x) * precanvasWitdhZoom + rerouteWidth;
|
|
var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y) * precanvasHeightZoom + rerouteWidth;
|
|
var x = eX;
|
|
var y = eY;
|
|
|
|
var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other');
|
|
linecurve += lineCurveSearch;
|
|
reoute_fix.push(lineCurveSearch);
|
|
}
|
|
|
|
});
|
|
if (reroute_fix_curvature) {
|
|
reoute_fix.forEach((itempath, i) => {
|
|
elems[item].children[i].setAttributeNS(null, 'd', itempath);
|
|
});
|
|
|
|
} else {
|
|
elems[item].children[0].setAttributeNS(null, 'd', linecurve);
|
|
}
|
|
|
|
}
|
|
})
|
|
|
|
var nodeIdInt = parseInt(id.slice(5));
|
|
if (this.nodes_to_frames_registry[nodeIdInt] !== undefined && this.nodes_to_frames_registry[nodeIdInt].length > 0) {
|
|
var _this = this;
|
|
this.nodes_to_frames_registry[nodeIdInt].forEach((frameNodeUuid) => {
|
|
const containedNodeIDs = _this.frame_to_nodes_registry[frameNodeUuid]
|
|
const frameNode = _this.container.querySelector('#framenode-' + frameNodeUuid)
|
|
_this.updateFrameNodePosition(frameNode, containedNodeIDs);
|
|
})
|
|
}
|
|
}
|
|
|
|
dblclick(e) {
|
|
if (this.connection_selected != null && this.reroute) {
|
|
this.createReroutePoint(this.connection_selected);
|
|
}
|
|
|
|
if (e.target.classList[0] === 'point') {
|
|
this.removeReroutePoint(e.target);
|
|
}
|
|
}
|
|
|
|
createReroutePoint(ele) {
|
|
this.connection_selected.classList.remove("selected");
|
|
const nodeUpdate = this.connection_selected.parentElement.classList[2].slice(9);
|
|
const nodeUpdateIn = this.connection_selected.parentElement.classList[1].slice(13);
|
|
const output_class = this.connection_selected.parentElement.classList[3];
|
|
const input_class = this.connection_selected.parentElement.classList[4];
|
|
this.connection_selected = null;
|
|
const point = document.createElementNS('http://www.w3.org/2000/svg', "circle");
|
|
point.classList.add("point");
|
|
var pos_x = this.pos_x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)));
|
|
var pos_y = this.pos_y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)));
|
|
|
|
point.setAttributeNS(null, 'cx', pos_x);
|
|
point.setAttributeNS(null, 'cy', pos_y);
|
|
point.setAttributeNS(null, 'r', this.reroute_width);
|
|
|
|
let position_add_array_point = 0;
|
|
if (this.reroute_fix_curvature) {
|
|
|
|
const numberPoints = ele.parentElement.querySelectorAll(".main-path").length;
|
|
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
|
|
path.classList.add("main-path");
|
|
path.setAttributeNS(null, 'd', '');
|
|
|
|
ele.parentElement.insertBefore(path, ele.parentElement.children[numberPoints]);
|
|
if (numberPoints === 1) {
|
|
ele.parentElement.appendChild(point);
|
|
} else {
|
|
const search_point = Array.from(ele.parentElement.children).indexOf(ele)
|
|
position_add_array_point = search_point;
|
|
ele.parentElement.insertBefore(point, ele.parentElement.children[search_point + numberPoints + 1]);
|
|
}
|
|
|
|
} else {
|
|
ele.parentElement.appendChild(point);
|
|
}
|
|
|
|
const nodeId = nodeUpdate.slice(5);
|
|
const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function (item, i) {
|
|
return item.node === nodeUpdateIn && item.output === input_class;
|
|
});
|
|
|
|
if (this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points === undefined) {
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points = [];
|
|
}
|
|
|
|
if (this.reroute_fix_curvature) {
|
|
|
|
if (position_add_array_point > 0 || this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points !== []) {
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.splice(position_add_array_point, 0, { pos_x: pos_x, pos_y: pos_y });
|
|
} else {
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y });
|
|
}
|
|
|
|
ele.parentElement.querySelectorAll(".main-path").forEach((item, i) => {
|
|
item.classList.remove("selected");
|
|
});
|
|
|
|
} else {
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y });
|
|
}
|
|
|
|
this.dispatch('addReroute', nodeId);
|
|
this.updateConnectionNodes(nodeUpdate);
|
|
}
|
|
|
|
removeReroutePoint(ele) {
|
|
const nodeUpdate = ele.parentElement.classList[2].slice(9)
|
|
const nodeUpdateIn = ele.parentElement.classList[1].slice(13);
|
|
const output_class = ele.parentElement.classList[3];
|
|
const input_class = ele.parentElement.classList[4];
|
|
|
|
let numberPointPosition = Array.from(ele.parentElement.children).indexOf(ele);
|
|
const nodeId = nodeUpdate.slice(5);
|
|
const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function (item, i) {
|
|
return item.node === nodeUpdateIn && item.output === input_class;
|
|
});
|
|
|
|
if (this.reroute_fix_curvature) {
|
|
const numberMainPath = ele.parentElement.querySelectorAll(".main-path").length
|
|
ele.parentElement.children[numberMainPath - 1].remove();
|
|
numberPointPosition -= numberMainPath;
|
|
if (numberPointPosition < 0) {
|
|
numberPointPosition = 0;
|
|
}
|
|
} else {
|
|
numberPointPosition--;
|
|
}
|
|
this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.splice(numberPointPosition, 1);
|
|
|
|
ele.remove();
|
|
this.dispatch('removeReroute', nodeId);
|
|
this.updateConnectionNodes(nodeUpdate);
|
|
}
|
|
|
|
registerNode(name, html, props = null, options = null) {
|
|
this.noderegister[name] = { html: html, props: props, options: options };
|
|
}
|
|
|
|
getNodeFromId(id) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
return JSON.parse(JSON.stringify(this.drawflow.drawflow[moduleName].data[id]));
|
|
}
|
|
getNodesFromName(name) {
|
|
var nodes = [];
|
|
const editor = this.drawflow.drawflow
|
|
Object.keys(editor).map(function (moduleName, index) {
|
|
for (var node in editor[moduleName].data) {
|
|
if (editor[moduleName].data[node].name == name) {
|
|
nodes.push(editor[moduleName].data[node].id);
|
|
}
|
|
}
|
|
});
|
|
return nodes;
|
|
}
|
|
|
|
addNode(name, num_in, num_out, ele_pos_x, ele_pos_y, classoverride, data, html, typenode = false) {
|
|
if (this.useuuid) {
|
|
var newNodeId = this.getUuid();
|
|
} else {
|
|
var newNodeId = this.nodeId;
|
|
}
|
|
const parent = document.createElement('div');
|
|
parent.classList.add("parent-node");
|
|
|
|
const node = document.createElement('div');
|
|
node.innerHTML = "";
|
|
node.setAttribute("id", "node-" + newNodeId);
|
|
node.classList.add("drawflow-node");
|
|
if (classoverride != '') {
|
|
node.classList.add(...classoverride.split(' '));
|
|
}
|
|
|
|
const inputs = document.createElement('div');
|
|
inputs.classList.add("inputs");
|
|
|
|
const outputs = document.createElement('div');
|
|
outputs.classList.add("outputs");
|
|
|
|
const json_inputs = {}
|
|
for (var x = 0; x < num_in; x++) {
|
|
const input = document.createElement('div');
|
|
input.classList.add("input");
|
|
input.classList.add("input_" + (x + 1));
|
|
json_inputs["input_" + (x + 1)] = { "connections": [] };
|
|
inputs.appendChild(input);
|
|
}
|
|
|
|
const json_outputs = {}
|
|
for (var x = 0; x < num_out; x++) {
|
|
const output = document.createElement('div');
|
|
output.classList.add("output");
|
|
output.classList.add("output_" + (x + 1));
|
|
json_outputs["output_" + (x + 1)] = { "connections": [] };
|
|
outputs.appendChild(output);
|
|
}
|
|
|
|
const content = document.createElement('div');
|
|
content.classList.add("drawflow_content_node");
|
|
if (typenode === false) {
|
|
content.innerHTML = html;
|
|
} else if (typenode === true) {
|
|
content.appendChild(this.noderegister[html].html.cloneNode(true));
|
|
} else {
|
|
if (parseInt(this.render.version) === 3) {
|
|
//Vue 3
|
|
let wrapper = this.render.h(this.noderegister[html].html, this.noderegister[html].props, this.noderegister[html].options);
|
|
wrapper.appContext = this.parent;
|
|
this.render.render(wrapper, content);
|
|
|
|
} else {
|
|
// Vue 2
|
|
let wrapper = new this.render({
|
|
parent: this.parent,
|
|
render: h => h(this.noderegister[html].html, { props: this.noderegister[html].props }),
|
|
...this.noderegister[html].options
|
|
}).$mount()
|
|
//
|
|
content.appendChild(wrapper.$el);
|
|
}
|
|
}
|
|
|
|
Object.entries(data).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(null, key[0], key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
function insertObjectkeys(object, name, completname) {
|
|
if (object === null) {
|
|
var object = data[name];
|
|
} else {
|
|
var object = object[name]
|
|
}
|
|
if (object !== null) {
|
|
Object.entries(object).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(object, key[0], completname + '-' + key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + completname + '-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
node.appendChild(inputs);
|
|
node.appendChild(content);
|
|
node.appendChild(outputs);
|
|
node.style.top = ele_pos_y + "px";
|
|
node.style.left = ele_pos_x + "px";
|
|
parent.appendChild(node);
|
|
this.precanvas.appendChild(parent);
|
|
var json = {
|
|
id: newNodeId,
|
|
name: name,
|
|
data: data,
|
|
class: classoverride,
|
|
html: html,
|
|
typenode: typenode,
|
|
inputs: json_inputs,
|
|
outputs: json_outputs,
|
|
pos_x: ele_pos_x,
|
|
pos_y: ele_pos_y,
|
|
}
|
|
this.drawflow.drawflow[this.module].data[newNodeId] = json;
|
|
this.dispatch('nodeCreated', newNodeId);
|
|
if (!this.useuuid) {
|
|
this.nodeId++;
|
|
}
|
|
return newNodeId;
|
|
}
|
|
|
|
addNodeImport(dataNode, precanvas) {
|
|
const buildConnectionLabels = this.buildConnectionLabels;
|
|
const parent = document.createElement('div');
|
|
parent.classList.add("parent-node");
|
|
|
|
const node = document.createElement('div');
|
|
node.innerHTML = "";
|
|
node.setAttribute("id", "node-" + dataNode.id);
|
|
node.classList.add("drawflow-node");
|
|
if (dataNode.class != '') {
|
|
node.classList.add(...dataNode.class.split(' '));
|
|
}
|
|
|
|
const inputs = document.createElement('div');
|
|
inputs.classList.add("inputs");
|
|
|
|
const outputs = document.createElement('div');
|
|
outputs.classList.add("outputs");
|
|
|
|
Object.keys(dataNode.inputs).map(function (input_item, index) {
|
|
const input = document.createElement('div');
|
|
input.classList.add("input");
|
|
input.classList.add(input_item);
|
|
inputs.appendChild(input);
|
|
Object.keys(dataNode.inputs[input_item].connections).map(function (output_item, index) {
|
|
|
|
var connection = document.createElementNS('http://www.w3.org/2000/svg', "svg");
|
|
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
|
|
path.classList.add("main-path");
|
|
path.setAttributeNS(null, 'd', '');
|
|
// path.innerHTML = 'a';
|
|
connection.classList.add("connection");
|
|
connection.classList.add("node_in_node-" + dataNode.id);
|
|
connection.classList.add("node_out_node-" + dataNode.inputs[input_item].connections[output_item].node);
|
|
connection.classList.add(dataNode.inputs[input_item].connections[output_item].input);
|
|
connection.classList.add(input_item);
|
|
|
|
connection.appendChild(path);
|
|
var labels = dataNode.inputs[input_item].connections[output_item].labels
|
|
if (labels) {
|
|
var connectionLabel = buildConnectionLabels(labels, dataNode.id, dataNode.inputs[input_item].connections[output_item].node)
|
|
connection.appendChild(connectionLabel);
|
|
}
|
|
precanvas.appendChild(connection);
|
|
|
|
});
|
|
});
|
|
|
|
for (var x = 0; x < Object.keys(dataNode.outputs).length; x++) {
|
|
const output = document.createElement('div');
|
|
output.classList.add("output");
|
|
output.classList.add("output_" + (x + 1));
|
|
outputs.appendChild(output);
|
|
}
|
|
|
|
const content = document.createElement('div');
|
|
content.classList.add("drawflow_content_node");
|
|
|
|
if (dataNode.typenode === false) {
|
|
content.innerHTML = dataNode.html;
|
|
} else if (dataNode.typenode === true) {
|
|
content.appendChild(this.noderegister[dataNode.html].html.cloneNode(true));
|
|
} else {
|
|
if (parseInt(this.render.version) === 3) {
|
|
//Vue 3
|
|
let wrapper = this.render.h(this.noderegister[dataNode.html].html, this.noderegister[dataNode.html].props, this.noderegister[dataNode.html].options);
|
|
wrapper.appContext = this.parent;
|
|
this.render.render(wrapper, content);
|
|
|
|
} else {
|
|
//Vue 2
|
|
let wrapper = new this.render({
|
|
parent: this.parent,
|
|
render: h => h(this.noderegister[dataNode.html].html, { props: this.noderegister[dataNode.html].props }),
|
|
...this.noderegister[dataNode.html].options
|
|
}).$mount()
|
|
content.appendChild(wrapper.$el);
|
|
}
|
|
}
|
|
|
|
Object.entries(dataNode.data).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(null, key[0], key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
function insertObjectkeys(object, name, completname) {
|
|
if (object === null) {
|
|
var object = dataNode.data[name];
|
|
} else {
|
|
var object = object[name]
|
|
}
|
|
if (object !== null) {
|
|
Object.entries(object).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(object, key[0], completname + '-' + key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + completname + '-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
node.appendChild(inputs);
|
|
node.appendChild(content);
|
|
node.appendChild(outputs);
|
|
node.style.top = dataNode.pos_y + "px";
|
|
node.style.left = dataNode.pos_x + "px";
|
|
parent.appendChild(node);
|
|
this.precanvas.appendChild(parent);
|
|
}
|
|
|
|
addRerouteImport(dataNode) {
|
|
const reroute_width = this.reroute_width
|
|
const reroute_fix_curvature = this.reroute_fix_curvature
|
|
const container = this.container;
|
|
Object.keys(dataNode.outputs).map(function (output_item, index) {
|
|
Object.keys(dataNode.outputs[output_item].connections).map(function (input_item, index) {
|
|
const points = dataNode.outputs[output_item].connections[input_item].points
|
|
if (points !== undefined) {
|
|
|
|
points.forEach((item, i) => {
|
|
const input_id = dataNode.outputs[output_item].connections[input_item].node;
|
|
const input_class = dataNode.outputs[output_item].connections[input_item].output;
|
|
const ele = container.querySelector('.connection.node_in_node-' + input_id + '.node_out_node-' + dataNode.id + '.' + output_item + '.' + input_class);
|
|
|
|
if (reroute_fix_curvature) {
|
|
if (i === 0) {
|
|
for (var z = 0; z < points.length; z++) {
|
|
var path = document.createElementNS('http://www.w3.org/2000/svg', "path");
|
|
path.classList.add("main-path");
|
|
path.setAttributeNS(null, 'd', '');
|
|
ele.appendChild(path);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
const point = document.createElementNS('http://www.w3.org/2000/svg', "circle");
|
|
point.classList.add("point");
|
|
var pos_x = item.pos_x;
|
|
var pos_y = item.pos_y;
|
|
|
|
point.setAttributeNS(null, 'cx', pos_x);
|
|
point.setAttributeNS(null, 'cy', pos_y);
|
|
point.setAttributeNS(null, 'r', reroute_width);
|
|
|
|
ele.appendChild(point);
|
|
});
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
addFrameNode(frameNodeConfig) {
|
|
frameNodeConfig.nodes = [...new Set(frameNodeConfig.nodes)]
|
|
if (frameNodeConfig.nodes.length == 0) {
|
|
return
|
|
}
|
|
|
|
var newNodeId = this.getUuid();
|
|
this.frame_to_nodes_registry[newNodeId] = frameNodeConfig.nodes
|
|
frameNodeConfig.nodes.forEach(nodeId => {
|
|
if (this.nodes_to_frames_registry[nodeId] === undefined) {
|
|
this.nodes_to_frames_registry[nodeId] = []
|
|
}
|
|
this.nodes_to_frames_registry[nodeId].push(newNodeId)
|
|
});
|
|
const parent = document.createElement('div');
|
|
parent.classList.add(...["parent-framenode"]);
|
|
|
|
const frameNode = document.createElement('div');
|
|
frameNode.innerHTML = '';
|
|
frameNode.setAttribute('id', 'framenode-' + newNodeId);
|
|
frameNode.classList.add(...['drawflow-framenode']);
|
|
if (frameNodeConfig.class !== undefined && frameNodeConfig.class != '') {
|
|
frameNode.classList.add(...frameNodeConfig.class.split(' '));
|
|
}
|
|
|
|
this.updateFrameNodePosition(frameNode, frameNodeConfig.nodes)
|
|
|
|
const frameTextNode = document.createElement('span');
|
|
frameTextNode.innerText = frameNodeConfig.text;
|
|
frameTextNode.classList.add('drawflow-framenode-text')
|
|
frameNode.appendChild(frameTextNode);
|
|
|
|
parent.appendChild(frameNode);
|
|
this.precanvas.appendChild(parent);
|
|
|
|
var json = {
|
|
id: newNodeId,
|
|
text: frameNodeConfig.text,
|
|
nodes: frameNodeConfig.nodes,
|
|
class: frameNodeConfig.class,
|
|
}
|
|
this.drawflow.drawflow[this.module].data._frames[newNodeId] = json;
|
|
this.dispatch('frameNodeCreated', newNodeId);
|
|
}
|
|
|
|
updateFrameNodePosition(frameNode, nodeIDs) {
|
|
if (!frameNode) {
|
|
return
|
|
}
|
|
|
|
var _this = this
|
|
var nodesHtml = nodeIDs.map(function (id) {
|
|
return _this.container.querySelector('#node-' + id)
|
|
})
|
|
|
|
function getFrameCoordinatesFromNodes(nodesHtml) {
|
|
var topLeft = { x: Number.MAX_SAFE_INTEGER, y: Number.MAX_SAFE_INTEGER }
|
|
var bottomRight = { x: Number.MIN_SAFE_INTEGER, y: Number.MIN_SAFE_INTEGER }
|
|
nodesHtml.forEach(function (nodeHtml) {
|
|
var bcr = nodeHtml.getBoundingClientRect()
|
|
topLeft.x = Math.min(topLeft.x, bcr.left)
|
|
topLeft.y = Math.min(topLeft.y, bcr.top)
|
|
bottomRight.x = Math.max(bottomRight.x, bcr.left + bcr.width)
|
|
bottomRight.y = Math.max(bottomRight.y, bcr.top + bcr.height)
|
|
})
|
|
return { topLeft: topLeft, bottomRight: bottomRight }
|
|
}
|
|
|
|
var frameCoordinates = getFrameCoordinatesFromNodes(nodesHtml)
|
|
|
|
var pos_x = frameCoordinates.topLeft.x - this.frameNodePadding.left / 2
|
|
var pos_y = frameCoordinates.topLeft.y - this.frameNodePadding.top / 2
|
|
var frameNodeHeight = (frameCoordinates.bottomRight.y - frameCoordinates.topLeft.y) + (this.frameNodePadding.top / 2 + this.frameNodePadding.bottom)
|
|
var frameNodeWidth = (frameCoordinates.bottomRight.x - frameCoordinates.topLeft.x) + (this.frameNodePadding.left / 2 + this.frameNodePadding.right)
|
|
|
|
var transpositionFactorX = (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom))
|
|
var transpositionOffsetX = -(this.precanvas.getBoundingClientRect().x * (this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)))
|
|
var transpositionFactorY = (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom))
|
|
var transpositionOffsetY = -(this.precanvas.getBoundingClientRect().y * (this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)))
|
|
|
|
pos_x = pos_x * transpositionFactorX + transpositionOffsetX
|
|
pos_y = pos_y * transpositionFactorY + transpositionOffsetY
|
|
frameNodeWidth = frameNodeWidth * transpositionFactorX
|
|
frameNodeHeight = frameNodeHeight * transpositionFactorY
|
|
|
|
frameNode.style.top = pos_y + 'px';
|
|
frameNode.style.left = pos_x + 'px';
|
|
frameNode.style.height = frameNodeHeight + 'px';
|
|
frameNode.style.width = frameNodeWidth + 'px';
|
|
}
|
|
|
|
updateFramenode(frameNodeUuid, frameNodeConfig) {
|
|
const frameNode = document.getElementById(frameNodeUuid);
|
|
frameNode.classList.remove(...frameNode.classList)
|
|
frameNode.classList.add(...['drawflow-framenode']);
|
|
if (frameNodeConfig.class !== undefined && frameNodeConfig.class != '') {
|
|
frameNode.classList.add(...frameNodeConfig.class.split(' '));
|
|
}
|
|
|
|
const frameTextNode = frameNode.querySelector('.drawflow-framenode-text')
|
|
frameTextNode.innerText = frameNodeConfig.text
|
|
|
|
var oldJson = this.drawflow.drawflow[this.module].data._frames[frameNodeUuid.slice(10)]
|
|
oldJson.text = frameNodeConfig.text
|
|
oldJson.class = frameNodeConfig.class
|
|
this.drawflow.drawflow[this.module].data._frames[frameNodeUuid.slice(10)] = oldJson;
|
|
|
|
this.dispatch('frameNodeUpdated', frameNodeUuid.slice(10));
|
|
}
|
|
|
|
updateNodeValue(event) {
|
|
var attr = event.target.attributes
|
|
for (var i = 0; i < attr.length; i++) {
|
|
if (attr[i].nodeName.startsWith('df-')) {
|
|
var keys = attr[i].nodeName.slice(3).split("-");
|
|
var target = this.drawflow.drawflow[this.module].data[event.target.closest(".drawflow_content_node").parentElement.id.slice(5)].data;
|
|
for (var index = 0; index < keys.length - 1; index += 1) {
|
|
if (target[keys[index]] == null) {
|
|
target[keys[index]] = {};
|
|
}
|
|
target = target[keys[index]];
|
|
}
|
|
target[keys[keys.length - 1]] = event.target.value;
|
|
if (event.target.isContentEditable) {
|
|
target[keys[keys.length - 1]] = event.target.innerText;
|
|
}
|
|
this.dispatch('nodeDataChanged', event.target.closest(".drawflow_content_node").parentElement.id.slice(5));
|
|
}
|
|
}
|
|
}
|
|
|
|
updateNodeDataFromId(id, data) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
this.drawflow.drawflow[moduleName].data[id].data = data;
|
|
if (this.module === moduleName) {
|
|
const content = this.container.querySelector('#node-' + id);
|
|
|
|
Object.entries(data).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(null, key[0], key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
function insertObjectkeys(object, name, completname) {
|
|
if (object === null) {
|
|
var object = data[name];
|
|
} else {
|
|
var object = object[name]
|
|
}
|
|
if (object !== null) {
|
|
Object.entries(object).forEach(function (key, value) {
|
|
if (typeof key[1] === "object") {
|
|
insertObjectkeys(object, key[0], completname + '-' + key[0]);
|
|
} else {
|
|
var elems = content.querySelectorAll('[df-' + completname + '-' + key[0] + ']');
|
|
for (var i = 0; i < elems.length; i++) {
|
|
elems[i].value = key[1];
|
|
if (elems[i].isContentEditable) {
|
|
elems[i].innerText = key[1];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
addNodeInput(id) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
const infoNode = this.getNodeFromId(id)
|
|
const numInputs = Object.keys(infoNode.inputs).length;
|
|
if (this.module === moduleName) {
|
|
//Draw input
|
|
const input = document.createElement('div');
|
|
input.classList.add("input");
|
|
input.classList.add("input_" + (numInputs + 1));
|
|
const parent = this.container.querySelector('#node-' + id + ' .inputs');
|
|
parent.appendChild(input);
|
|
this.updateConnectionNodes('node-' + id);
|
|
|
|
}
|
|
this.drawflow.drawflow[moduleName].data[id].inputs["input_" + (numInputs + 1)] = { "connections": [] };
|
|
}
|
|
|
|
addNodeOutput(id) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
const infoNode = this.getNodeFromId(id)
|
|
const numOutputs = Object.keys(infoNode.outputs).length;
|
|
if (this.module === moduleName) {
|
|
//Draw output
|
|
const output = document.createElement('div');
|
|
output.classList.add("output");
|
|
output.classList.add("output_" + (numOutputs + 1));
|
|
const parent = this.container.querySelector('#node-' + id + ' .outputs');
|
|
parent.appendChild(output);
|
|
this.updateConnectionNodes('node-' + id);
|
|
|
|
}
|
|
this.drawflow.drawflow[moduleName].data[id].outputs["output_" + (numOutputs + 1)] = { "connections": [] };
|
|
}
|
|
|
|
removeNodeInput(id, input_class) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
const infoNode = this.getNodeFromId(id)
|
|
if (this.module === moduleName) {
|
|
this.container.querySelector('#node-' + id + ' .inputs .input.' + input_class).remove();
|
|
}
|
|
const removeInputs = [];
|
|
Object.keys(infoNode.inputs[input_class].connections).map(function (key, index) {
|
|
const id_output = infoNode.inputs[input_class].connections[index].node;
|
|
const output_class = infoNode.inputs[input_class].connections[index].input;
|
|
removeInputs.push({ id_output, id, output_class, input_class })
|
|
})
|
|
// Remove connections
|
|
removeInputs.forEach((item, i) => {
|
|
this.removeSingleConnection(item.id_output, item.id, item.output_class, item.input_class);
|
|
});
|
|
|
|
delete this.drawflow.drawflow[moduleName].data[id].inputs[input_class];
|
|
|
|
// Update connection
|
|
const connections = [];
|
|
const connectionsInputs = this.drawflow.drawflow[moduleName].data[id].inputs
|
|
Object.keys(connectionsInputs).map(function (key, index) {
|
|
connections.push(connectionsInputs[key]);
|
|
});
|
|
this.drawflow.drawflow[moduleName].data[id].inputs = {};
|
|
const input_class_id = input_class.slice(6);
|
|
let nodeUpdates = [];
|
|
connections.forEach((item, i) => {
|
|
item.connections.forEach((itemx, f) => {
|
|
nodeUpdates.push(itemx);
|
|
});
|
|
this.drawflow.drawflow[moduleName].data[id].inputs['input_' + (i + 1)] = item;
|
|
});
|
|
nodeUpdates = new Set(nodeUpdates.map(e => JSON.stringify(e)));
|
|
nodeUpdates = Array.from(nodeUpdates).map(e => JSON.parse(e));
|
|
|
|
if (this.module === moduleName) {
|
|
const eles = this.container.querySelectorAll("#node-" + id + " .inputs .input");
|
|
eles.forEach((item, i) => {
|
|
const id_class = item.classList[1].slice(6);
|
|
if (parseInt(input_class_id) < parseInt(id_class)) {
|
|
item.classList.remove('input_' + id_class);
|
|
item.classList.add('input_' + (id_class - 1));
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
nodeUpdates.forEach((itemx, i) => {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections.forEach((itemz, g) => {
|
|
if (itemz.node == id) {
|
|
const output_id = itemz.output.slice(6);
|
|
if (parseInt(input_class_id) < parseInt(output_id)) {
|
|
if (this.module === moduleName) {
|
|
const ele = this.container.querySelector(".connection.node_in_node-" + id + ".node_out_node-" + itemx.node + "." + itemx.input + ".input_" + output_id);
|
|
ele.classList.remove('input_' + output_id);
|
|
ele.classList.add('input_' + (output_id - 1));
|
|
}
|
|
if (itemz.points) {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections[g] = { node: itemz.node, output: 'input_' + (output_id - 1), points: itemz.points }
|
|
} else {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections[g] = { node: itemz.node, output: 'input_' + (output_id - 1) }
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
this.updateConnectionNodes('node-' + id);
|
|
}
|
|
|
|
removeNodeOutput(id, output_class) {
|
|
var moduleName = this.getModuleFromNodeId(id)
|
|
const infoNode = this.getNodeFromId(id)
|
|
if (this.module === moduleName) {
|
|
this.container.querySelector('#node-' + id + ' .outputs .output.' + output_class).remove();
|
|
}
|
|
const removeOutputs = [];
|
|
Object.keys(infoNode.outputs[output_class].connections).map(function (key, index) {
|
|
const id_input = infoNode.outputs[output_class].connections[index].node;
|
|
const input_class = infoNode.outputs[output_class].connections[index].output;
|
|
removeOutputs.push({ id, id_input, output_class, input_class })
|
|
})
|
|
// Remove connections
|
|
removeOutputs.forEach((item, i) => {
|
|
this.removeSingleConnection(item.id, item.id_input, item.output_class, item.input_class);
|
|
});
|
|
|
|
delete this.drawflow.drawflow[moduleName].data[id].outputs[output_class];
|
|
|
|
// Update connection
|
|
const connections = [];
|
|
const connectionsOuputs = this.drawflow.drawflow[moduleName].data[id].outputs
|
|
Object.keys(connectionsOuputs).map(function (key, index) {
|
|
connections.push(connectionsOuputs[key]);
|
|
});
|
|
this.drawflow.drawflow[moduleName].data[id].outputs = {};
|
|
const output_class_id = output_class.slice(7);
|
|
let nodeUpdates = [];
|
|
connections.forEach((item, i) => {
|
|
item.connections.forEach((itemx, f) => {
|
|
nodeUpdates.push({ node: itemx.node, output: itemx.output });
|
|
});
|
|
this.drawflow.drawflow[moduleName].data[id].outputs['output_' + (i + 1)] = item;
|
|
});
|
|
nodeUpdates = new Set(nodeUpdates.map(e => JSON.stringify(e)));
|
|
nodeUpdates = Array.from(nodeUpdates).map(e => JSON.parse(e));
|
|
|
|
if (this.module === moduleName) {
|
|
const eles = this.container.querySelectorAll("#node-" + id + " .outputs .output");
|
|
eles.forEach((item, i) => {
|
|
const id_class = item.classList[1].slice(7);
|
|
if (parseInt(output_class_id) < parseInt(id_class)) {
|
|
item.classList.remove('output_' + id_class);
|
|
item.classList.add('output_' + (id_class - 1));
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
nodeUpdates.forEach((itemx, i) => {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections.forEach((itemz, g) => {
|
|
if (itemz.node == id) {
|
|
const input_id = itemz.input.slice(7);
|
|
if (parseInt(output_class_id) < parseInt(input_id)) {
|
|
if (this.module === moduleName) {
|
|
|
|
const ele = this.container.querySelector(".connection.node_in_node-" + itemx.node + ".node_out_node-" + id + ".output_" + input_id + "." + itemx.output);
|
|
ele.classList.remove('output_' + input_id);
|
|
ele.classList.remove(itemx.output);
|
|
ele.classList.add('output_' + (input_id - 1));
|
|
ele.classList.add(itemx.output);
|
|
}
|
|
if (itemz.points) {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections[g] = { node: itemz.node, input: 'output_' + (input_id - 1), points: itemz.points }
|
|
} else {
|
|
this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections[g] = { node: itemz.node, input: 'output_' + (input_id - 1) }
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
this.updateConnectionNodes('node-' + id);
|
|
}
|
|
|
|
removeNodeId(id) {
|
|
this.removeConnectionNodeId(id);
|
|
var moduleName = this.getModuleFromNodeId(id.slice(5))
|
|
if (this.module === moduleName) {
|
|
this.container.querySelector(`#${id}`).remove();
|
|
}
|
|
|
|
var _this = this
|
|
var new_frame_to_nodes_registry = []
|
|
if (this.nodes_to_frames_registry[id.slice(5)] !== undefined) {
|
|
this.nodes_to_frames_registry[id.slice(5)].forEach((frameUuid) => {
|
|
new_frame_to_nodes_registry = _this.frame_to_nodes_registry[frameUuid].filter((nodeId) => {
|
|
return id.slice(5) != nodeId;
|
|
})
|
|
if (new_frame_to_nodes_registry.length == 0) {
|
|
_this.removeFrameNodeId('framenode-' + frameUuid)
|
|
} else {
|
|
const frameNode = _this.container.querySelector('#framenode-' + frameUuid)
|
|
_this.frame_to_nodes_registry[frameUuid] = new_frame_to_nodes_registry
|
|
_this.updateFrameNodePosition(frameNode, _this.frame_to_nodes_registry[frameUuid]);
|
|
}
|
|
})
|
|
delete this.nodes_to_frames_registry[id.slice(5)]
|
|
}
|
|
|
|
delete this.drawflow.drawflow[moduleName].data[id.slice(5)];
|
|
this.dispatch('nodeRemoved', id.slice(5));
|
|
}
|
|
|
|
removeConnection() {
|
|
if (this.connection_selected != null) {
|
|
var listclass = this.connection_selected.parentElement.classList;
|
|
this.connection_selected.parentElement.remove();
|
|
//console.log(listclass);
|
|
var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[1].slice(13) && item.output === listclass[4]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out, 1);
|
|
|
|
var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[2].slice(14) && item.input === listclass[3]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in, 1);
|
|
this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] });
|
|
this.connection_selected = null;
|
|
}
|
|
}
|
|
|
|
removeSingleConnection(id_output, id_input, output_class, input_class) {
|
|
var nodeOneModule = this.getModuleFromNodeId(id_output);
|
|
var nodeTwoModule = this.getModuleFromNodeId(id_input);
|
|
if (nodeOneModule === nodeTwoModule) {
|
|
// Check nodes in same module.
|
|
|
|
// Check connection exist
|
|
var exists = this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.findIndex(function (item, i) {
|
|
return item.node == id_input && item.output === input_class
|
|
});
|
|
if (exists > -1) {
|
|
|
|
if (this.module === nodeOneModule) {
|
|
// In same module with view.
|
|
this.container.querySelector('.connection.node_in_node-' + id_input + '.node_out_node-' + id_output + '.' + output_class + '.' + input_class).remove();
|
|
}
|
|
|
|
var index_out = this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.findIndex(function (item, i) {
|
|
return item.node == id_input && item.output === input_class
|
|
});
|
|
this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.splice(index_out, 1);
|
|
|
|
var index_in = this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.findIndex(function (item, i) {
|
|
return item.node == id_output && item.input === output_class
|
|
});
|
|
this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.splice(index_in, 1);
|
|
|
|
this.dispatch('connectionRemoved', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class });
|
|
return true;
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
removeConnectionNodeId(id) {
|
|
const idSearchIn = 'node_in_' + id;
|
|
const idSearchOut = 'node_out_' + id;
|
|
|
|
const elemsOut = this.container.querySelectorAll(`.${idSearchOut}`);
|
|
for (var i = elemsOut.length - 1; i >= 0; i--) {
|
|
var listclass = elemsOut[i].classList;
|
|
|
|
var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[2].slice(14) && item.input === listclass[3]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in, 1);
|
|
|
|
var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[1].slice(13) && item.output === listclass[4]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out, 1);
|
|
|
|
elemsOut[i].remove();
|
|
|
|
this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] });
|
|
}
|
|
|
|
const elemsIn = this.container.querySelectorAll(`.${idSearchIn}`);
|
|
for (var i = elemsIn.length - 1; i >= 0; i--) {
|
|
|
|
var listclass = elemsIn[i].classList;
|
|
|
|
var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[1].slice(13) && item.output === listclass[4]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out, 1);
|
|
|
|
var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function (item, i) {
|
|
return item.node === listclass[2].slice(14) && item.input === listclass[3]
|
|
});
|
|
this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in, 1);
|
|
|
|
elemsIn[i].remove();
|
|
|
|
this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] });
|
|
}
|
|
}
|
|
|
|
removeFrameNodeId(fullID) {
|
|
const frameUuid = fullID.slice(10);
|
|
const moduleName = this.getModuleFromNodeId(this.frame_to_nodes_registry[frameUuid][0])
|
|
this.container.querySelector(`#${fullID}`).remove();
|
|
var _this = this;
|
|
this.frame_to_nodes_registry[frameUuid].forEach((nodeID) => {
|
|
_this.nodes_to_frames_registry[nodeID] = _this.nodes_to_frames_registry[nodeID].filter((frameNodeUuid) => {
|
|
return frameNodeUuid != frameUuid;
|
|
})
|
|
})
|
|
delete this.frame_to_nodes_registry[frameUuid];
|
|
delete this.drawflow.drawflow[moduleName].data._frames[frameUuid];
|
|
this.dispatch('frameNodeRemoved', frameUuid);
|
|
}
|
|
|
|
getModuleFromNodeId(id) {
|
|
var nameModule;
|
|
const editor = this.drawflow.drawflow
|
|
Object.keys(editor).map(function (moduleName, index) {
|
|
Object.keys(editor[moduleName].data).map(function (node, index2) {
|
|
if (node == id) {
|
|
nameModule = moduleName;
|
|
}
|
|
})
|
|
});
|
|
return nameModule;
|
|
}
|
|
|
|
addModule(name) {
|
|
this.drawflow.drawflow[name] = { "data": { "_frames": {} } };
|
|
this.dispatch('moduleCreated', name);
|
|
}
|
|
changeModule(name) {
|
|
this.dispatch('moduleChanged', name);
|
|
this.module = name;
|
|
this.precanvas.innerHTML = "";
|
|
this.canvas_x = 0;
|
|
this.canvas_y = 0;
|
|
this.pos_x = 0;
|
|
this.pos_y = 0;
|
|
this.mouse_x = 0;
|
|
this.mouse_y = 0;
|
|
this.zoom = 1;
|
|
this.zoom_last_value = 1;
|
|
this.precanvas.style.transform = '';
|
|
this.import(this.drawflow, false);
|
|
}
|
|
|
|
removeModule(name) {
|
|
if (this.module === name) {
|
|
this.changeModule('Home');
|
|
}
|
|
delete this.drawflow.drawflow[name];
|
|
this.dispatch('moduleRemoved', name);
|
|
}
|
|
|
|
clearModuleSelected() {
|
|
this.precanvas.innerHTML = "";
|
|
this.drawflow.drawflow[this.module] = { "data": { "_frames": {}} };
|
|
this.frame_to_nodes_registry = {};
|
|
this.nodes_to_frames_registry = {};
|
|
}
|
|
|
|
clear() {
|
|
this.precanvas.innerHTML = "";
|
|
this.drawflow = { "drawflow": { "Home": { "data": { "_frames": {} } } } };
|
|
this.frame_to_nodes_registry = {};
|
|
this.nodes_to_frames_registry = {};
|
|
}
|
|
export() {
|
|
const dataExport = JSON.parse(JSON.stringify(this.drawflow));
|
|
this.dispatch('export', dataExport);
|
|
return dataExport;
|
|
}
|
|
|
|
import(data, notifi = true) {
|
|
this.clear();
|
|
this.drawflow = JSON.parse(JSON.stringify(data));
|
|
this.load();
|
|
if (notifi) {
|
|
this.dispatch('import', 'import');
|
|
}
|
|
}
|
|
|
|
/* Events */
|
|
on(event, callback) {
|
|
// Check if the callback is not a function
|
|
if (typeof callback !== 'function') {
|
|
console.error(`The listener callback must be a function, the given type is ${typeof callback}`);
|
|
return false;
|
|
}
|
|
// Check if the event is not a string
|
|
if (typeof event !== 'string') {
|
|
console.error(`The event name must be a string, the given type is ${typeof event}`);
|
|
return false;
|
|
}
|
|
// Check if this event not exists
|
|
if (this.events[event] === undefined) {
|
|
this.events[event] = {
|
|
listeners: []
|
|
}
|
|
}
|
|
this.events[event].listeners.push(callback);
|
|
}
|
|
|
|
removeListener(event, callback) {
|
|
// Check if this event not exists
|
|
|
|
if (!this.events[event]) return false
|
|
|
|
const listeners = this.events[event].listeners
|
|
const listenerIndex = listeners.indexOf(callback)
|
|
const hasListener = listenerIndex > -1
|
|
if (hasListener) listeners.splice(listenerIndex, 1)
|
|
}
|
|
|
|
dispatch(event, details) {
|
|
// Check if this event not exists
|
|
if (this.events[event] === undefined) {
|
|
// console.error(`This event: ${event} does not exist`);
|
|
return false;
|
|
}
|
|
this.events[event].listeners.forEach((listener) => {
|
|
listener(details);
|
|
});
|
|
}
|
|
|
|
getUuid() {
|
|
// http://www.ietf.org/rfc/rfc4122.txt
|
|
var s = [];
|
|
var hexDigits = "0123456789abcdef";
|
|
for (var i = 0; i < 36; i++) {
|
|
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
|
}
|
|
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
|
|
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
|
|
s[8] = s[13] = s[18] = s[23] = "-";
|
|
|
|
var uuid = s.join("");
|
|
return uuid;
|
|
}
|
|
}
|