Closed Flyfot-Finesse closed 1 year ago
Hi @apmkstudio
It's not possible.
The only thing I can think of is: An editor inside the node. This would be possible.
Duplicate:
Hi @jerosoler ,
Thanks for your quick reply.
The editor inside the node doesn't support the goal we are trying to achieve. Any plan of adding this in the near future as I see this has been requested by many other users?
Or if you can guide how we can customize the library to achieve this?
Appreciate your help!
Regards, Ankit
I have been doing a test and it seems to work, without modifying the library. Listening to the events
Complet code example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.css"/>
<script src="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.js"></script>
</head>
<div id="drawflow"></div>
<style>
#drawflow {
position: relative;
text-align:initial;
width: 100%;
height: 800px;
border: 1px solid red;
}
.drawflow svg {
z-index: 1;
}
.drawflow .drawflow-node.GROUP {
width: 500px;
height: 500px;
z-index: 0;
}
.drawflow .drawflow-node.GROUP.hover-drop {
background: pink;
}
</style>
<script>
var id = document.getElementById("drawflow");
const editor = new Drawflow(id);
editor.start();
editor.addNode('aaa', 1, 1, 600, 200, 'aaa', {}, `aaa` );
editor.addNode('bbb', 1, 1, 850, 200, 'bbb', {}, `bbb` );
editor.addNode('ccc', 1, 1, 850, 370, 'ccc', {}, `ccc`);
editor.addConnection(1, 2, 'output_1', 'input_1');
editor.addConnection(2, 3, 'output_1', 'input_1');
editor.addNode('GROUP', 0, 0, 1200, 100, 'GROUP', { elements: []}, `` );
editor.addNode('GROUP', 0, 0, 0, 100, 'GROUP', { elements: []}, `` );
let dragElementHover = null;
let last_x = 0;
let last_y = 0;
editor.on("mouseMove", ({x,y}) => {
if(editor.node_selected && editor.drag && editor.node_selected.classList[1] !== "GROUP") {
const eles = document.elementsFromPoint(x,y);
const ele = eles.filter( ele => ele.classList[1] === "GROUP");
if(ele.length > 0) {
dragElementHover = ele[0];
dragElementHover.classList.add("hover-drop");
} else {
if(dragElementHover != null) {
dragElementHover.classList.remove("hover-drop");
dragElementHover = null;
}
}
} else if(editor.node_selected && editor.drag && editor.node_selected.classList[1] == "GROUP") {
const dragNode = editor.node_selected.id.slice(5);
const dragNodeInfo = editor.getNodeFromId(dragNode);
const elements = dragNodeInfo.data.elements;
elements.forEach(eleN => {
const node = document.getElementById(`node-${eleN}`);
var xnew = (last_x - x) * editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom);
var ynew = (last_y - y) * editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom);
node.style.top = (node.offsetTop - ynew) + "px";
node.style.left = (node.offsetLeft - xnew) + "px";
editor.drawflow.drawflow[editor.module].data[eleN].pos_x = (node.offsetLeft - xnew);
editor.drawflow.drawflow[editor.module].data[eleN].pos_y = (node.offsetTop - ynew);
editor.updateConnectionNodes(`node-${eleN}`);
});
}
last_x = x;
last_y = y;
})
editor.on("nodeMoved", (id) => {
const dragNode = id;
if(dragElementHover !== null) {
const dropNode = dragElementHover.id.slice(5);
if(dragNode !== dropNode) {
removeOfGroupNode(dragNode);
dragElementHover.classList.remove("hover-drop");
const dropNodeInfo = editor.getNodeFromId(dropNode);
const dropNodeInfoData = dropNodeInfo.data;
if(dropNodeInfoData.elements.indexOf(dragNode) === -1) {
dropNodeInfoData.elements.push(dragNode);
editor.updateNodeDataFromId(dropNode, dropNodeInfoData);
}
}
dragElementHover = null;
} else {
removeOfGroupNode(dragNode);
}
})
editor.on("nodeRemoved", (id) => {
removeOfGroupNode(id);
});
function removeOfGroupNode(id) {
Object.keys(editor.drawflow.drawflow[editor.module].data).forEach(ele => {
if(editor.drawflow.drawflow[editor.module].data[ele].class === "GROUP") {
const findIndex = editor.drawflow.drawflow[editor.module].data[ele].data.elements.indexOf(id);
if(findIndex !== -1) {
editor.drawflow.drawflow[editor.module].data[ele].data.elements.splice(findIndex, 1);
}
}
})
}
</script>
</body>
</html>
Hi @jerosoler ,
Thanks a lot for the sample code this works great for now.
Appreciate your support !!
Regards, Ankit
Hello @jerosoler,
Can you help me with one more task please, I want the ability that the group node is height adjustable how can I do that can you please guide me? ie when I click on the group node I can have the option to increase the height of the node.
Thanks & Regards, Ankit
Use resize both, to modify the node.
Change css to:
.drawflow .drawflow-node.GROUP {
width: 500px;
height: 300px;
z-index: 0;
resize: both;
overflow: auto;
}
The problem is that when an element is dragable it doesn't work and you have to do this trick.
And add javascript:
editor.on("clickEnd", (e) => {
if(editor.node_selected) {
const diffClick = 15;
const height = editor.node_selected.getBoundingClientRect().height/editor.zoom - diffClick;
const width = editor.node_selected.getBoundingClientRect().width/editor.zoom - diffClick;
const xClick = e.offsetX;
const yClick = e.offsetY;
if(yClick >= height && xClick >= width) {
editor.drag = false;
}
}
});
In this example, these changes will not be saved in the export, but you can save them in the node. For when I get the import back. Same as done in the element group.
Thanks @jerosoler ,
Works fine, can you please give a sample of how to save height / width in the node? and when import again we can how the height of the node will be same as it was set before ?
Appreciate it thanks!!
Regards, Ankit
Also is there any hook/ callback before the nodes load basically I want to do is group elements and show them as in kanban board so how to set X / Y axis dynamically on flow load?
Use event "import" to the detect load complete and move node.
View move node by javascript:
Hi @jerosoler ,
I tried event import it doesn't work for me
editor.on('import', function (id) { console.log("import done"); })
Basically I want to save the width and height of the group column and on load (import) the height should be same as before
Thanks, Ankit
Did you add it before the import or after? You have to go before.
I tried after - let me try before and get back to you
I tried before it triggers but cannot modify the content of node
editor.on('import', function (data) { editor.drawflow.drawflow.Home.data[14].class = 'test'; console.log(editor.drawflow.drawflow.Home.data[14]) })
If you modify the class in the node, it is not updated in the view automatically.
Or you modify it before importing. Or you modify the node as well.
Do you mean directly modifying the variable before import?
If you modify the variable before importing.
When importing, it loads the node correctly.
If not you will have to modify the node class by javascript. Since when updating the data is not reflected automatically.
Hello @jerosoler ,
Thanks for the reply!
I tried before import also, but I am not able to save the custom width/height of the node can you please guide me on it how to set the width/height of the node on import and save it when drag-drop, thanks!
Basically what we would like is once the user stretch the width/height of the node (we save into the database the json) and again when the user comes to the page the node width/height is the same as the user set it previously.
Regards, Ankit
Hello @jerosoler ,
Can you please guide me on the above as it's critical for the project that the width and height are saved properly.
Appreciate your support.
Thanks, Ankit
So you can get the height and width of element resized.
let resizeElement = false;
editor.on("clickEnd", (e) => {
if(editor.node_selected) {
const diffClick = 20;
const height = editor.node_selected.getBoundingClientRect().height/editor.zoom - diffClick;
const width = editor.node_selected.getBoundingClientRect().width/editor.zoom - diffClick;
const xClick = e.offsetX;
const yClick = e.offsetY;
if(yClick >= height && xClick >= width) {
resizeElement = true;
editor.drag = false;
}
}
});
editor.on("mouseUp", (e) => {
if(resizeElement) {
console.log(`Resize Node ${editor.node_selected.id} - Width: ${editor.node_selected.style.width} - Height: ${editor.node_selected.style.height}`)
// editor.drawflow.drawflow[editor.module].data[editor.node_selected.id].width = ...;
resizeElement = false;
}
});
Hello @jerosoler ,
Yes thanks for that but the issue is how I save it in the json so that this data can be used again to set height /width of the node on page reload ?
Thanks, Ankit
Uncomment this line.
// editor.drawflow.drawflow[editor.module].data[editor.node_selected.id].width = ...;
Create the line for the height.
Use the on "import" event method. To set width and height.
Hello @jerosoler ,
Sorry but I am not able to modify the css class on import event can you please give an example how we can achieve it easily, thanks!
@apmkstudio view example:
Hello @jerosoler,
I have followed the example code but I am not able to modify the node for example change class or style or any other node json parameter. See screenshot below
In console the first parameter only returns string "import"
Code screenshot
Thanks, Ankit
Event import only return one parameter.
you have to loop through the array and modify the class...
Yes but that parameter is just a string so I cannot modify it.
You can loop through the same object that you passed in when importing. Or editor.drawflow. Or editor.export();
Yes, I tried that too but unfortunately, it modifies the JSON object but not DOM even after updating using
editor.updateConnectionNodes(node-
+ index)
I want the dom class to update so I can do some changes infact I want height to update dynamically based on whats saved in node.
Just for your information, I am not using VUE JS I am using simple javascript on the page. Technically in a Laravel blade file if this helps...
First of all does it save the height and width of the node? Where in?.
Second, editor.updateConnectionNodes updates connections, not nodes.
Understand what you are doing at each moment.
I have added height and width to the node directly in json
"1": { "id": 1, "name": "welcome", "data": {}, "class": "welcome", "html": "\n <div>\n <div class=\"title-box\">👏 Welcome!!</div>\n <div class=\"box\">\n <p>Simple flow library <b>demo</b>\n <a href=\"https://github.com/jerosoler/Drawflow\" target=\"_blank\">Drawflow</a> by <b>Jero Soler</b></p><br>\n\n <p>Multiple input / outputs<br>\n Data sync nodes<br>\n Import / export<br>\n Modules support<br>\n Simple use<br>\n Type: Fixed or Edit<br>\n Events: view console<br>\n Pure Javascript<br>\n </p>\n <br>\n <p><b><u>Shortkeys:</u></b></p>\n <p>🎹 <b>Delete</b> for remove selected<br>\n 💠 Mouse Left Click == Move<br>\n ❌ Mouse Right == Delete Option<br>\n 🔍 Ctrl + Wheel == Zoom<br>\n 📱 Mobile support<br>\n ...</p>\n </div>\n </div>\n ", "typenode": false, "inputs": {}, "outputs": {}, "pos_x": 50, "pos_y": 50, "height": 333, },
But when the page loads that data is not accessible for me before dom updated. Is there a method to update node I guess its updateNodeDataFromId() but it doesn't allow to change the height via JS I want the Group node height to be adjustable and stay same on page load. Appreciate if you can help on it.
View:
editor.start();
const loadJson = {
"drawflow": {
"Home": {
"data": {
"1": {
"id": 1,
"name": "welcome",
"data": {},
"class": "welcome",
"html": "Test1",
"typenode": false,
"inputs": {},
"outputs": {},
"pos_x": 50,
"pos_y": 50,
"height": 333,
"width": 200,
},
"2": {
"id": 2,
"name": "welcome",
"data": {},
"class": "welcome",
"html": "Test2",
"typenode": false,
"inputs": {},
"outputs": {},
"pos_x": 200,
"pos_y": 350,
"height": 400,
"width": 500,
},
}
}
}
}
editor.on("import", () => {
Object.entries(editor.drawflow.drawflow['Home'].data).forEach(ele => {
const id = ele[1].id;
const width = ele[1].width;
const height = ele[1].height;
const node = editor.container.querySelector(`#node-${id}`);
node.style.width = width + "px";
node.style.height = height + "px";
});
});
editor.import(loadJson);
Thanks @jerosoler works fine!
Hey @jerosoler, referencing your code example for creating group nodes, how would you additionally include reroute points within the group node, so that when the group node is repositioned, the reroute points are also repositioned? Thank you!
https://user-images.githubusercontent.com/5437674/185522622-19ff9624-3089-4245-86e3-5fcc98722216.mp4
Hi @brucesundberg
Try adding:
node.style.left = (node.offsetLeft - xnew) + "px";
//New Code
const points = document.querySelectorAll(`.connection.node_out_node-${eleN} circle`);
points.forEach(p => {
const px = p.getAttributeNS(null, 'cx') - xnew;
const py = p.getAttributeNS(null, 'cy') - ynew;
p.setAttributeNS(null, 'cx', px);
p.setAttributeNS(null, 'cy', py);
Object.keys(editor.drawflow.drawflow[editor.module].data[eleN].outputs).forEach(output => {
console.log(output);
editor.drawflow.drawflow[editor.module].data[eleN].outputs[output].connections.forEach(con => {
con.points.forEach(point => {
point.pos_x = px;
point.pos_y = py;
})
})
});
});
// End new Code
editor.drawflow.drawflow[editor.module].data[eleN].pos_x = (node.offsetLeft - xnew);
Thank you a ton, @jerosoler! Works perfectly!
Não funciona corretamente quando usado o "mini-map"; new DrawflowMinimap(idMinimap, editor, 0.1);
Hey @jerosoler, referencing your code example for creating group nodes, how would you additionally include reroute points within the group node, so that when the group node is repositioned, the reroute points are also repositioned? Thank you!
reroute.anchor.mp4
hey please can you show the code how you have added multiple nodes in a group i want to group child nodes. without hovering on
Thanks for your great work. How to support nested group nodes?
Hello @jerosoler ,
Firstly great library!!
I am using this library on a project but we have a customized requirement to group Nodes in a wrapper and allow to link nodes from multiple groups to connect to each other. Something like on demo of another library link below: https://demo.jsplumbtoolkit.com/groups/
Can you please guide how can we achieve this with Drawflow?
Thanks & Regards, Ankit