draggable icon indicating copy to clipboard operation
draggable copied to clipboard

Prevent dragging on child interactive element

Open a-korzun opened this issue 7 years ago • 13 comments

Hi there! Does Draggable support to prevent drag event on any interactive child element? Example: I have a list with items that contains checkbox, it is so hard to check input w/o drag element.

Live Preview: https://codepen.io/akorzun/pen/aYwXoR

Gif: mar-23-2018 15-20-57

a-korzun avatar Mar 23 '18 12:03 a-korzun

You could do something clever on drag:start that looks at the mouse position and compares it against the position of the button, and cancel if its overtop of that button. Perhaps that would work.

@tsov what do you think about introducing a class like .draggable-cancel or .draggable-prevent-default, and if a drag is initiated when the touch or mouse or whatever is overtop that element, the drag never happens? That way, users can have child links / buttons that can be clicked while still being within a draggable item.

beefchimi avatar Mar 23 '18 13:03 beefchimi

@beefchimi ok, thank. I have a solution https://codepen.io/akorzun/pen/aYwXoR

Hope this idea is not so terrible to implement into this project.

a-korzun avatar Mar 23 '18 14:03 a-korzun

@katasup One way to get around the issue is to increase the default drag delay:

new Draggable(containers, {
  // ...
  delay: 300,
  // ...
})

that way there is enough time to check/uncheck checkboxes or even click links/buttons, but also allow to start dragging when holding the mouse down longer.

@beefchimi We could create a plugin that automatically prevents dragging when the target is an input field or even contenteditable, what do you think?

tsov avatar Mar 23 '18 14:03 tsov

@tsov I feel like thats a good start... but we should offer something more flexible.

Let's say I have a div instead of a button because "reasons". And I want a click on that div to trigger some action unrelated to dragging. I feel like I should have an easy way to tell draggable "ignore dragging if I'm clicking on this child element".

My expectation is to:

  • add a class to that "undraggable child element"
  • include a certain option to the draggable instance (or using a certain plugin)

Then Draggable will know to cancel when attempting to drag an item where that "undraggable child element" is the target.

beefchimi avatar Mar 23 '18 14:03 beefchimi

What is the status of this?

I'm running into a similar issue - pop-up modal with textareas, child element of draggable div. When user tries to select text 'draggable' class is added to the modal and a ghost-image of it floats behind the modal.

Would love to be able to disable draggable on child elements...

jhull avatar May 18 '18 16:05 jhull

I think I've "tried" to overcome this issue before by giving a handle using :not, however, I'm not sure if that actually works

ncovercash avatar May 19 '18 02:05 ncovercash

@narrative1st interesting, could you elaborate a little more? I want to understand the problem a little more to give a better solution to your problem. A codepen or code example of sorts would be best.

The proposed solution in this issue, can be done manually too (without building out that plugin)

tsov avatar May 20 '18 15:05 tsov

I solved it by moving the child elements into a portal and rendering them outside the draggable component with vue-portal. In the simplest of terms, when you highlight a text selection on a modal above the draggable element, drag thinks you want to drag the elements underneath.

Moving the modal outside of the draggable section fixed the problem for me.

jhull avatar Jun 04 '18 16:06 jhull

To disable dragging of a component, I dynamically remove the draggable class. This works well for me.

fdietze avatar Jul 23 '18 08:07 fdietze

I solved this problem with mouseover and mouseout events. So, when the user hover on input, select, button, it will update a boolean variable. Then, you can do a check with the boolean.

chunhei37 avatar Aug 28 '18 18:08 chunhei37

@beefchimi I'd love to see a plugin that prevents the drag if it's a click coming from a child! A class seems like a really nice declarative way to do that. Right now i'm going to implement something similar to @katasup's solution

sudara avatar Sep 01 '18 17:09 sudara

For people who could have this problem later, I solved it with adding handle on Sortable object, with this handle you can add like button and be able to move that item only on that element by targeting him with class

const sortable = new Sortable(document.querySelectorAll("ul"), {
      draggable: "li",
      handle: ".handle-drag"
    })

AidPuska avatar Jan 30 '24 16:01 AidPuska