Shopify / draggable

The JavaScript Drag & Drop library your grandparents warned you about.
https://shopify.github.io/draggable
MIT License
18k stars 1.09k forks source link

Interferes with dragging within children #463

Closed jasonvarga closed 3 years ago

jasonvarga commented 3 years ago

Excuse the horrible title.

I'm using shopify/draggable to make a handful of tiptap editors reorderable. When I do that, the editors lose their drag and drop behavior.

This might be an issue on their end, but I'm posting this here too because maybe you can see something obvious that I'm doing wrong. Ref: https://github.com/ueberdosis/tiptap/issues/918

Here's a video of the issue: https://d.pr/v/AqYC6r You can see me successfully dragging and moving text in the first standalone editor, but failing in the second which is wrapped by sortable.

Here's a codesandbox with the issue: https://codesandbox.io/s/tiptap-prosemirror-draggable-issue-1f34o It's written in Vue, but the part where sortable is used is pretty straightforward.

zjffun commented 3 years ago

Seems to be caused by our preventing the default dragstart behavior.

https://github.com/Shopify/draggable/blob/1590e5de8bcb3b50b33fa46aef5462f9f8a896ae/src/Draggable/Sensors/MouseSensor/MouseSensor.js#L95

<div contenteditable id="foo">hello world</div>
<script>
    function preventNativeDragStart(e) {
        e.preventDefault();
    }
    foo.addEventListener('dragstart', preventNativeDragStart);
</script>
jasonvarga commented 3 years ago

I assume that's pretty necessary for draggable to work though?

Not suggesting this is a solution, but what if that mousedown handler returned early if the event target is within a contenteditable?

zjffun commented 3 years ago

Indeed. I think most people might want to prevent the native dragstart by default, such as dragging an input element. Therefore, I am trying to return early when the target isn't in handle or draggable elements.

Currently, temporary fixes can be made by stopPropagation, for example:

<div contenteditable id="foo">with out preventNativeDragStart</div>
<div>
    other content
    <input type="text" value="test1 test2">
</div>
<script>
    function preventNativeDragStart(e) {
        e.preventDefault();
    }
    document.addEventListener('dragstart', preventNativeDragStart);

    foo.addEventListener('dragstart', function (e) {
        e.stopPropagation();
    })
</script>
jasonvarga commented 3 years ago

Thanks for clarifying. This did fix the issue for me. I'm happy to close this, but you can reopen if you think it's a bug.

Appreciate the quick help!