Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Current best practice for drag-and-drop?
41 points by couchand on Aug 19, 2014 | hide | past | web | favorite | 26 comments
I'm working on an application that makes heavy use of in-app drag-and-drop to categorize and update data. We aren't using the DnD for sorting or arbitrary item placement, nor do we support dropping files or other media for upload. We simply need to be able to drag a type of element and handle hovering and dropping on others of that type as well as their container. We also only need to support Firefox and Chrome.

Originally it was built with HTML5 drag-and-drop, but we've started to see many issues, specifically in Chrome. For instance, previously we got a ghost image of the element for free in both Firefox and Chrome, but recently Chrome has reverted to a little gray box with the element text. We could use setDragImage, but since we're dragging plain old DOM elements that seems excessive. Chrome also seems to treat the dragEnter events strangely, making nested element hover handling difficult.

We could potentially implement a custom solution (the front-end is React, so it wouldn't be too hard) but that also seems excessive.

I'm about to add a dependency on jQuery and jQuery UI just to allow the use of their bulletproof Draggable and Droppable elements. Somehow that feels dirty. Is there a good, modern way to allow us to drag regular DOM elements and handle the hover and drop events? It doesn't seem like it should be this hard.

From experience writing an app with loads of complex DnD, I strongly recommend giving up on DnD libraries if you are doing anything beyond some generic sortable list thing. You will never get the library to do what you want it to do, and even if you get close, the performance will be fucking abysmal, for reasons that become obvious when you've programmed your first DnD interaction by hand. It's just not something a library can reasonably handle, because to cover multiple use cases they have to put loads of conditional logic inside a mousemove listener, which kills performance. DnD interactions are very application-specific; to me the term DnD refers to a class of problems and a corresponding skill set, not a feature that you can delegate away. And as you have discovered, the HTML5 DnD API is a pile of shit.

Do not fear making your own drag interactions from raw mouse events. I avoided it for ages, then discovered it is easier than I expected, and satisfying because what you produce is so much better quality. It's just combinations of mousedown, mousemove, mouseenter, mouseleave, and mouseup, and the confidence to attach/detach listeners for those events on the fly during the interaction. Also by thinking about the whole event sequence on a lower level you will often realise a better way to design the UX of the interaction.

Thanks for the support. Eventually I think this is the way we'll go. For the time being I'm putting up with dropping in jQuery UI, but I think my next big project will be a few React mixins for UI interactions like this.

My comment earlier was a bit strong; there are obviously cases when you just need to get the job done, and if jQuery UI covers your use case with an acceptable perf hit then go with it.

If you want a halfway house, I've just remembered this little jQuery plugin, not well known at all, but it is the best thing available:


For me this plugin was a bridge between using DnD libraries and writing raw mouse listeners. It basically just fires off events at key points during a drag sequence, and it's up to you to update element styles to move them around... ie, you can't see anything physically happening on the page unless you update the DOM yourself (not difficult). It's basically sugar around mouse events to make them a lot less intimidating, eg, on each move it gives you the mouse position relative to wherever the drag started, so you don't have to keep track of this yourself.

Compared to any regular DnD library, it's better performing and miles more flexible. It's almost as good as doing it with raw mouse events. Look at the demos and view the code, they are impressive. It's old though. Hope it still works with modern jQuery.

Use a well tested library,even if it means extra load.The reason for this is DnD apis are a nightmare that will work on 90% of the devices and browsers but not on the rest. Trust libraries that are well tested over a wide range of browsers.

> I'm about to add a dependency on jQuery and jQuery UI just to allow the use of their bulletproof Draggable and Droppable elements. Somehow that feels dirty.

What feels even more dirty is a UI that doesnt work properly across browsers.Better have a solid UI rather than thinking using jQuery == DIRTY.

As I said, we don't need to support anything other than Firefox and Chrome. It's an internal app, we know everyone's on modern versions.

And as I mentioned in another comment, jQuery itself isn't dirty, but adding a dependency on a swiss army knife library for just one feature does seem dirty.

The bulletproof way would probably be to use a library to handle drag and drop. If you're not wanting to use jQuery UI just for DnD functionality, there are a couple libraries that do drag and drop exclusively.

1. http://gtramontina.github.io/draggable.js/ 2. http://kbjr.github.io/DragDrop/index.html

We looked at both of these libraries and it seems neither supports hover and drop events, so it seems like the front runner is still jQuery UI.

FYI, unlike most new HTML5 standards which were discussed in the WHATWG list and added to the standard based on developers' needs, "HTML5" DnD is a standardization of the bizarre implementation of Drag and Drop used by some web pages after Microsoft introduced as part of Internet Explorer 5 in 1999. Don't expect it to be a sane foundation for what you want to do.

I agree with everyone recommending a tried and tested library for this.

Even with jQuery and jQuery UI, I see a few bugs and inconsistencies across browsers from time to time. However, you only have to look at the bug trackers for those projects to see how many more issues they have already resolved in this area.

I’m all for keeping things light and avoiding unnecessary dependencies on external libraries, but this is one of those issues where you’d be mad to try and get everything working properly yourself. This is one of the nastiest, most edge-case-ridden areas of front-end web development today, and you surely have better things to do with your time than fix every browser oddity one by one.

DOM support is broken, especially when you need cross-browser compatibility. Guess what jQuery was built to solve?

In other words, do not worry - it is not dirty, it is exactly the purpose of jQuery.

Oh! This might be the best spot to ask. I'm trying to build a web app (ipad kiosk) that has drag and drop and scrolling. The code works perfectly on desktop w/ trackpad because scroll and click are two different actions. Mobile it looks like I have to re-write the scrolling logic because there are only touch events exposed? Is there another way?

I'm currently trying JQUI with touchpunch and have considered hammer.js. Anyone have experience with scrolling and dnd on mobile?

This is trivial in a native iOS app: you just look for two touches and call that scrolling. Does the framework you are working with expose all of the touch events?

It could. So you are saying two fingers for scroll then, yes? I'll try that.

It is actually my trackpad not the iPad that uses two finger scroll. I assumed they were the same, and I guess I don't really notice how I scroll on the iPad. I am sure a two-finger scroll will work, but it is not the native recommendation like I though.

The native iOS answer is actually if the finger is static for a certain time interval then it is a click, but if it begins moving immediately then it is a scroll (swipe).

The best spot to ask is probably Stack Overflow.

I suggest you check out how Wordpress does this in the menu-settings. They support nested dropping and it's pretty smooth in both Firefox and Chrome.

It is not dirty, jQuery and jQuery UI have been tried and tested. I wouldn't reinvent the wheel here unless you need to.

Don't get me wrong, I love jQuery. What's dirty about it is including the whole library when all we really need is UI's Draggable and Droppable. jQuery UI does have a custom download builder, so that's good.

yeah I would just include the elements of JQuery UI you need. I just implemented a drag to cart feature on an site I am working on and it works great.

My thoughts exactly. Just use the download builder (http://jqueryui.com/download/) to choose the features you need a la carte.

I was working on a blog post on implementing drag and drop using functional reactive programming (FRP) with bacon.js. Your question just pushed me to finish it :)

Here it is.


I started a small module to do that without any dependency: https://github.com/bpierre/minidrag#minidrag-

Same problem, also working with react. Setting react to work with this libraries result in more effort than writing it manually.

No kidding. If you're planning on using jQuery UI, do it in `componentDidMount` and add this to your Draggable options:

           helper: ->                                                   
             el = jQuery this                                           
               .removeAttr "id"                                         
             el.find "*"                                                
               .removeAttr "data-reactid"                               

There are libs on github just about html5 DnD... When I have the time I will test them to remove jquery-ui from my projects.

Have you tried dropzonejs? Works pretty fine, one can even drag & drop folders of folders(chrome only)

Registration is open for Startup School 2019. Classes start July 22nd.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact