Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: allow updating of target selectors list during a drag #82

Open
panayotisk opened this issue Jul 16, 2022 · 6 comments
Open

Comments

@panayotisk
Copy link

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: #253 I think this request is important enough to deserve a separate issue submission.

@sporritt
Copy link
Member

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

@panayotisk
Copy link
Author

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 #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.

@sporritt
Copy link
Member

sporritt commented Aug 1, 2022

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)
  }
})

@sporritt
Copy link
Member

sporritt commented Aug 2, 2022

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.

@panayotisk
Copy link
Author

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.

@panayotisk
Copy link
Author

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.

@sporritt sporritt transferred this issue from jsplumb/jsplumb Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants