Open panayotisk opened 2 years ago
I am a bit wary of this idea. Do you think you could achieve what you want with the concept of "position finders":
https://blog.jsplumbtoolkit.com/2022/02/10/anchor-position-finder
Hmm maybe. I did not know of this feature! It might solve our issue with the DOM elements. In this case I do not need the handler elements, and write the appropriate position finder code. What confuses me is that during drag I would like to highlight the side (face) that will host the anchor and, as described in jsplumb/community-edition#253, I do not know what mouse event to use in order to achieve it. Maybe you have a tip on this? This is important for UX because the user should know where the drop will position their connection.
I probably wouldnt do the hover with jsplumb, it could be done with a couple of event listeners that you manage:
https://jsfiddle.net/8zq5ohb7/1/
<div id="container">
<div id="aDiv" class="el"></div>
<div id="anotherDiv" class="el"></div>
</div>
// remove al classes
function reset(e) {
e.target.classList.remove("north", "south", "east", "west")
}
// calculate distance between two points
function dist(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
}
container.addEventListener("mousemove", (e) => {
if (e.target.classList.contains("el")) {
reset(e)
const b = e.target.getBoundingClientRect(),
// prepare an array of midpoints for each face
faces = [
[ "north", b.x + (b.width/ 2), b.y ],
[ "south", b.x + (b.width / 2), b.y + b.height ],
[ "east", b.x + b.width, b.y + (b.height / 2) ],
[ "west", b.x, b.y + (b.height / 2) ],
]
// sort midpoints by distance from event's page location
faces.sort((a,b) => {
return dist(a[1], a[2], e.pageX, e.pageY) - dist(b[1], b[2], e.pageX, e.pageY)
})
// add the class corresponding to the closest midpoint to the element
e.target.classList.add(faces[0][0])
}
})
container.addEventListener("mouseout", (e) => {
if (e.target.classList.contains("el")) {
reset(e)
}
})
i should point out that in this case the event listeners are on the container and they're checking for an "el" class on the elements. This might be a little simplified from a real world use case because here the nodes dont have any child elements; in the real world this would probably need tweaking, in particular the mousemove
listener, as the events won't necessarily be coming from the node element. The mouseout
event would probably be fired by the node elements, though, regardless of their content.
You may need to attach a delegated event handler, or of course you could attach this listener to every node. but i know you want to render some large datasets and your focus is on performance.
I will be trying your suggestions and get back to you as soon as I manage to have something that is working for our case.
I finally got the time to test your suggestion of showing the desirable handler by using simple javascript. For determining the source handler (left-right-top-bottom) this works pretty well. For determining the target handler (while dragging the connection endpoint) there is the problem that mouse events are consumed by jsplumb so the mousemove event stops working. This was described here Maybe you have some tip what to do for determining the handler while dragging?
A code sandbox that uses your code above with jsplumb is here My issue is how to display handlers on target nodes, since all I got is the jtk-drag-hover class.
version: jsplumb 5.8.3 description: This request is about allowing recalculation of target selectors (through a function call) during a drag. The reason is to avoid always rendering DOM elements for connection handlers and thus having a very reduced DOM size. If we could somehow create DOM elements for connection handlers only when hovering over a node, we would drastically reduce the number of DOM nodes on the page. In our case this means 4 connection handlers (left, right, up, down) per node. We made performance benchmarks on our page with and without the rendering of connection handlers and there is significant difference on large DOMs. I do not know if it is possible at all to modify the jsplumb setup in order to support this request, however if it can be done it would improve the performance of our application a lot. initial (relevant) issue: jsplumb/community-edition#253 I think this request is important enough to deserve a separate issue submission.