Vue.Draggable icon indicating copy to clipboard operation
Vue.Draggable copied to clipboard

How to cancel drop when hitting escape

Open itm-platform opened this issue 4 years ago • 6 comments

Hi there,

I have two different lists with the same group to interchange items between them.

Hitting escape in the middle of a drag operation cancels the drag operation and lets the item on its original list only if the dragged element wasn't already over the destination list. If the dragged element is already over the destination, hitting escape acts as if I dropped the item (triggers unchoose, add and so on)

I need to be able to hit escape at any moment and cancel the whole operation, leaving the item on its original list.

I did read the :move prop but it doesn't seem to help on this. (by the way, the two links are broken on: "See complete example: Cancel.html, cancel.js")

Thanks for your help

itm-platform avatar Dec 07 '20 13:12 itm-platform

I came here for this reason as well. Not only does escape persist the current move position, but also dragging to an invalid location outside the list (you can a stop cursor) and releasing the drag-drop persists at the last move position. In both cases I want the change to be reverted. Both of these standard user-scenarios seem like user cancellation of the operation...

Agendum avatar Jan 12 '21 08:01 Agendum

Is there a solution for this?

mapkbalaji avatar Mar 25 '21 10:03 mapkbalaji

The same question. How make cancel if user dragging to an invalid location outside the list.

VitalyaK avatar Feb 08 '22 08:02 VitalyaK

Partial solution

Theoretically, we should be able to check whether the drop was canceled or not, using the native drag-and-drop API:

  • https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations
  • https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/dropEffect but it seems that the property isn’t set and we have the following:
onDragEnd(event) {
  if (event.originalEvent.dataTransfer.dropEffect == "none")
    // this is always true as if the event was always canceled...

:-(

However, a couple other properties can be seen as candidates for discriminating between the “drop“ and the “cancel“ operations:

      //   - event.originalEvent.type ...............: "drop" vs. "dragend"
      //   - event.originalEvent.returnValue ........: false = drop, true = cancel
      //   - event.originalEvent.defaultPrevented ...: true = drop, false = cancel

:-)

image

Remaining problems

This works for the "Escape" key press, but I haven't tried it with a drop outside of the drop area...

Also another problem remains: in another implementation of draggable, it doesn't listen to the Escape key at all. I don't know how to make it do so and reuse the solution I have found. (Alternatively, I can listen for the Escape key being pressed, but I don't know how to make it trigger the process that leads to onDragEnd.)

deskobj avatar Aug 12 '22 12:08 deskobj

I found a hacky workaround for this problem with wasting 2 hours 😷. I've checked the code and it seems to be a bug.

// On template: <draggable ref="draggableComponentRefName">
// On mounted() or somewhere: set sortable.js option directly
setTimeout(() => {
  this.$refs.draggableComponentRefName._sortable.option('onMove', (evt, originalEvent) => {
    console.log({evt, originalEvent})
    debugger
    return false
  })
}, 500)

kwbtdisk avatar Oct 15 '22 17:10 kwbtdisk

I ended up checking dataTransfer.items which is an empty array if the drag is canceled with escape key.

onAdd(event) {
      //if the drag was canceled with ESC
      if (event.originalEvent.dataTransfer.items.length === 0) {
        return
      }
}

andreasjeppsson avatar Dec 16 '22 10:12 andreasjeppsson