react-dnd / react-dnd-html5-backend

HTML5 backend for React DnD [Legacy Repo]
MIT License
146 stars 97 forks source link

Support for modifier keys while dragging #23

Open andersfly opened 8 years ago

andersfly commented 8 years ago

Right now it doesn't seem like modifier keys are supported while dragging items.

By modifier keys I mean like pressing the alt key to enter copy 'mode' instead of move 'mode'. Just like when moving files around in the Mac OS finder app, you have the option to hold down alt to copy instead of move.

A trivial solution to this, would be to listen for keydown events on the window while dragging, and then alter some state indicating whether or not it should copy. Unfortunately keyboard events won't trigger while dragging. (apparently the browser enters some 'drag' mode) Making this impossible.

However the HTML5 drag and drop api does support modifier keys: https://developer.mozilla.org/en-US/docs/Web/Events/drag

But since this is abstracted away in the backend, it needs to support this somehow, and propagate it to the 'end user' components.

Question is was this left out for some reason? Maybe bad performance?

gaearon commented 8 years ago

It’s something I didn’t have the need for, so I didn’t implement it. Instead, what I needed was specifying dropEffect per drag source so React DnD lets you do that:

return connectDragSource(<div />, { dropEffect: 'copy' })

I’m open to considering a pull request that somehow supports having user specify the behavior by keys if you have a specific API proposal for this. Personally I don’t plan to work on this feature.

andersfly commented 8 years ago

I put some effort into investigating this. And I actually came up with a work-around. The events: drag, dragover gets fired every time you move your mouse while dragging. And obviously these events also bubble, making it possible to catch them in a hoc setting a top your DragSource, DragLayer etc. and then rerender the underlying component. E.g.

export default detectDragModifierKeys()(
  DragSource(ItemTypes.FANCY_ITEM, myItemSource, myItemCollect)(MyItem)
);

This actually works, although a little awkward. Also if you listen for the event on the window, its possible to make all components aware of the current drag event, and what modifier keys might be pressed or not. This is particularly useful for a DragLayer. Do mind performance though :-)

One caveat though, is that the Drag'n'Drop API is extremely quirky at times, and modifier keys won't be detected on the drag event in Firefox. So in a real world scenario you would have to use dragover event instead. This event also gets fired on every mousemove, and when listening for the event on window/document, it has (afaik) pretty much the same effect.

I could be nice though, to have it directly supported in react dnd, and I'm planning to give it a shot at some time. But for now the above solution will do the trick. (If anyone out there is desperate, I'm happy to share a gist or something)

andersfly commented 8 years ago

Here is the gist: https://gist.github.com/andersfly/25ab13dbd1acc5eb915f

lukeknep commented 8 years ago

My org would love this feature. I've had to do a workaround similar to @andersfly's.

hpurmann commented 7 years ago

@lukeknep, @andersfly This may be interesting for you: https://github.com/gaearon/react-dnd-html5-backend/issues/58

t1mmen commented 7 years ago

On behalf on @Timely I'm offering a US$100 for getting this feature implemented & released as part of the official react-dnd/react-dnd-html5-backend package.

Requirements:

Related issues:

I'd be happy to transfer the bounty to the project maintainers for escrow.

/cc @lukeknep @andersfly @hpurmann