Quantcast
Channel: Active questions tagged svelte - Stack Overflow
Viewing all articles
Browse latest Browse all 1815

Drag and drop event propagation

$
0
0

I'm attempting to setup drag and drop in my project

I've got several fields setup like thisenter image description hereIf a user clicks the image on the left and drags, they can re-order the rows

When a valid dropzone is detected (in this case, any other row is a valid dropzone) a class is applied to the div wrapping all elements of that row which renders a border underneath to indicate where the dropped row will be insertedenter image description here

My problem is, for some reason, if I drag a row over one of the input or select elements that are a child of the dropzone, they are concidered to be the dropzone rather than the underlying element.enter image description hereIts a little hard to see but theres a dashed line under the right most input indicating my dropzone class has been added.

How its setup

The following JS is called for each valid dropzone

function dropzone(node, options) {  console.log(`created dropzone on ${node}`);  let state = {    dropEffect: "move",    dragover_class: ["dropzone", "pb-3"],    ...options,  };  function handle_dragenter(e) {    console.log(`DragEnter ${e.target}`);    e.stopPropagation();    e.target.classList.add(...state.dragover_class);  }  function handle_dragleave(e) {    console.log(`DragLeave ${e.target}`);    e.stopPropagation();    e.target.classList.remove(...state.dragover_class);  }  function handle_dragover(e) {    console.log(`DragOver ${e.target}`);    e.stopPropagation();    e.dataTransfer.dropEffect = state.dropEffect;  }  node.addEventListener("dragenter", handle_dragenter, true);  node.addEventListener("dragleave", handle_dragleave, true);  node.addEventListener("dragover", handle_dragover, true);}

What I've tried

CSS

I've tried adding pointer-events: none; to all children of my dropzone class thats added in my dragenter handler which works but only when the dropzone is successfully entered before any of its children. I've also tried blanked setting pointer-events: none; on all child elements of dropzones which does fix the issue but it also prevents the inputs from working

JS

I've tried setting useCapture to true when adding my event listeners via addEventListener and calling e.stopPropagation() inside all of my handlers which to my understanding should cause the node the event listener is added to (in this case, the dropzone row) to be called first before propogating down to all children. However, the inputs are still receiving dragenter events

useCapture feels like the most promising approach but I must me missing something here (or it doesnt work on drag events for some reason).

Can anyone see anything obviously wrong with my setup or provide me with any other suggestions to fix my issue?

EDIT: I've gotten things working reasonably well by

  1. using this rather than e.target in my handlers. Turns out e.target always references the element the event fired on (i.e. what your mouse if over) where as this or e.currentTarget references the element with the listener attached
  2. Even with the above, I was leave and enter events firing when I moved the mouse between any of the children of a dropzone which caused lots of graphical issues. This was fixed by implementing a basic reference counter so whenever you dragenter fires, the counter is incremented and when dragleave is fired its decremented. The class adding the underline is only removed when this counter reaches 0.

I'm still open to suggestions that can make this better but I'm happy with the current result


Viewing all articles
Browse latest Browse all 1815

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>