Sortable icon indicating copy to clipboard operation
Sortable copied to clipboard

Esc to abort drag?

Open dandv opened this issue 11 years ago • 9 comments

Right now there seems to be no way to cancel dragging an element. If the user started to drag an item and changed their mind, they have to remember where the element started from, and drag it back there. Esc just drops the element, as does releasing the mouse button.

Would it be more useful if Esc aborted the drag operation and animated the element back in its original place?

dandv avatar Dec 01 '14 14:12 dandv

Have to think, it sounds reasonable.

RubaXa avatar Dec 01 '14 14:12 RubaXa

Kendo UI Core Sortable has a nice implementation of this feature.

dandv avatar Dec 01 '14 15:12 dandv

https://github.com/RubaXa/Sortable/blob/master/Sortable.js#L514 needs to be modified like this:

else if (dragEl.nextSibling !== nextEl && evt.dataTransfer.dropEffect !== 'none') {
// Update event if element was dragged, and Esc was not pressed
...undo drag code here?...

dandv avatar Dec 05 '14 10:12 dandv

  1. The element is already moved.
  2. If it is a touch-device: evt.dataTransfer === undefined

RubaXa avatar Dec 05 '14 10:12 RubaXa

Well yes, on a touch device you can't press Esc. What would be the code to move the element back? Seems like onStart should store the start position (prevSibling || nextSibling), then onEnd would move the element to that stored start position, after prevSibling (unless it was the first element) or before nextSibling otherwise.

dandv avatar Dec 05 '14 19:12 dandv

Well yes, on a touch device you can't press Esc. What would be the code to move the element back? Seems like onStart should store the start position (prevSibling || nextSibling), then onEnd would move the element to that stored start position, after prevSibling (unless it was the first element) or before nextSibling otherwise.

dandv avatar Dec 05 '14 19:12 dandv

Looking forward for this. Any ETA @owen-m1 ?

smg99 avatar Apr 20 '20 02:04 smg99

I've written a plugin to support this feature. Have a look:

/**
 * Returns the CancelSort Sortable
 * Plugin, to cancel a drag action
 * by hitting the ESC key.
 * 
 * @returns {Function}
 */
export function CancelSortPlugin() {
  function CancelSort() {
    this.defaults = {
      cancelSort: true,
      revertOnSpill: true
    };
  }

  CancelSort.prototype = {
    drop({ cancel, dispatchSortableEvent, originalEvent, dragEl, cloneEl }) {
      // In case the 'ESC' key was hit,
      // the origEvent is of type 'dragEnd'.
      if (originalEvent.type === 'dragend') {

        // Call revert on spill, to revert the drag
        // using the existing algorithm.
        this.sortable.revertOnSpill.onSpill(...arguments);

        // Undo changes on the drag element.
        if (dragEl) {
          // Remove ghost & chosen class.
          dragEl.classList.remove(this.options.ghostClass);
          dragEl.classList.remove(this.options.chosenClass);
          dragEl.removeAttribute('draggable');
        }

        // In case of a copy, the cloneEl
        // has to be removed again.
        if (cloneEl) {
          cloneEl.remove();
        }

        // Dispatch 'end' event.
        dispatchSortableEvent('end');
      }
    }
  }

  return Object.assign(CancelSort, {
    pluginName: 'cancelSort'
  });
}

And make use of it like this:

import Sortable from 'sortablejs';
import { CancelSortPlugin } from './path/to/plugin/sortable-cancel-plugin.js';

Sortable.mount(CancelSortPlugin());

This will cancel (or revert) d&d when the user hits 'ESC', even if the object was already inserted in another list. Disabling this plugin during runtime is not possible, but can be easily added.

philSixZero avatar May 02 '22 09:05 philSixZero

Still no official change or fix for this yet?

mitirius avatar Dec 11 '23 16:12 mitirius