Click here to Skip to main content
15,891,976 members
Articles / Web Development / HTML5

Add support for standard HTML5 Drag and Drop operations on Mobile Devices

Rate me:
Please Sign up or sign in to vote.
4.97/5 (27 votes)
11 Apr 2016CPOL4 min read 79.2K   2.7K   8   5
Polyfill that enables HTML5 drag drop support on mobile (touch) devices.

The Problem

The HTML5 specification includes support for drag and drop operations.

This is supported by all modern desktop browsers, but not by mobile browsers running under Android and IOS. This is a problem because one of the main reasons to develop applications using HTML5 is the ability to run on all devices.

I suspect mobile browsers don't support drag and drop for two reasons:

  1. Their screens are often too small for useful drag/drop operations.
  2. They use touch for other tasks such as scrolling and zooming, which could interfere with D&D.

But many mobile devices have screens that are large enough. This includes pretty much all tablets and a lot of phones. And not being able to scroll or zoom by dragging some elements (those with a draggable attribute) in exchange for drag/drop support seems like a reasonable trade-off.

Therefore, in order to use drag and drop on mobile devices today, you have two options:

  1. Forget about the HTML5 drag and drop APIs and use a custom drag-drop library (your own, or one of several existing options); or
  2. Use a polyfill that translates touch events into HTML5 drag and drop events.

We prefer the second approach because standards are important. Following the HTML drag and drop standard instead of using a custom library means your existing drag and drop code will work with standards-based frameworks and components without significant changes.

For example, several Wijmo controls use HTML5 drag and drop extensively:

  • The FlexGrid uses it to re-arrange and resize rows and columns.
  • The GroupPanel uses it to re-arrange and sort groups.
  • The PivotPanel uses it to build OLAP views and to provide context-menus.

Unfortunately, until recently all this functionality was limited or non-existent when running on mobile devices. You could drag and drop grid columns, groups, and pivot fields with the mouse, but not using touch.

The Solution

When our customers told us they wanted support for drag and drop operations on mobile devices, we decided to follow the polyfill approach, and implemented a DragDropTouch class that translates touch events into HTML5 drag and drop events transparently. This allowed us to improve touch support for all our controls at once, without having to change any of the controls.

The DragDropTouch polyfill works as follows:

  • It attaches listeners to touch events.
  • On touchstart, it checks whether the target element has the draggable attribute or is contained in an element that does. If that is the case, it saves a reference to this “drag source” element and prevents the default handling of the event.
  • On touchmove, it checks whether the touch has moved a certain threshold distance from the origin. If that is the case, it raises the dragstart event and continues monitoring moves to fire dragenter and dragleave.
  • On touchend, it raises the dragend and drop events.

This is enough to handle drag and drop, but is not enough to fully support touch. The problem is that once a touch is detected on a draggable element, the default handling of the event must be prevented in order to prevent scrolling. But not all touches are meant to start drag operations. The user may simply want to click/tap the element, or double-click it, or display a context menu.

In other words, it is not enough to provide drag and drop support for touch actions; the polyfill must not interfere when the touch is not a drag and drop action.

Because of this requirement, the polyfill must perform a few additional tasks:

  • Raise the mousemove, mousedown, mouseup, and click events when the user touches a draggable element but doesn’t start dragging,
  • Raise the dblclick event when there's a new touchstart right after a click, and
  • Raise the contextmenu event when the touch lasts a while but the user doesn’t start dragging the element.

That’s all there is to it.

Using the polyfill is easy. All you have to do is add this script tag to your pages:

<script src="scripts/DragDropTouch.js"></script>

The script will automatically create an instance of the DragDropTouch class and will start translating the events, enabling drag and drop operations to work on Android and IOS devices the same way they work on desktop browsers.

We have created a sample that demonstrates the effect of the polyfill using a classic HTML5 drag drop sample as well as some Wijmo controls. You can see the sample in action here:

    http://bernardo-castilho.github.io/DragDropTouch/demo/

The picture below shows the sample running on an iPad while the user drags element A to a new position:

Image 1Screenshot of dragging on iPad

Conclusion

Implementing a polyfill to translate touch actions into drag-drop events is an efficient way to improve the usability of standards-based components so they support drag and drop actions on mobile devices.

The polyfill described above extends mouse support to several Wijmo controls that support drag and drop operations, but it is generic, so it will work with other standards-based components and applications as well.

All you have to do is add one script tag to your application, open it on your iPad, and drag away!

This article contains a lot of interesting information on different types of pointer events, including mouse, touch, and the proposed standard for single set of “pointer events”:

    http://www.html5rocks.com/en/mobile/touchandmouse/

And this article focuses specifically on HTML5 drag and drop:

    http://www.html5rocks.com/en/tutorials/dnd/basics/

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Brazil Brazil
Software Architect/Developer with several years experience creating and delivering software.

Full-stack Web development (including React, Firebase, TypeScript, HTML, CSS), Entity Framework, C#, MS SQL Server.

Passionate about new technologies and always keen to learn new things as well as improve on existing skills.

Comments and Discussions

 
QuestionAppreciation and Feedback Pin
Bitifet17-Jan-24 12:41
professionalBitifet17-Jan-24 12:41 
First of all, I'd like to add my thanks to those expressed by the other users for so wonderful work.

I've just landed in this great community, which I didn't know about before, and I'm still processing how great it looks.

I'd also share my thoughts in case they could result of interest to anyone:

First of all I'd notice that the "Download source and demo" link seems to be outdated: It didn't work to me and, since the live demo linked at the end of the article did, I dug into its source to download its DragDropTouch.js version which worked quite fine.

I would probably end up not using it (or at least not without any customization) because I want to support touch drag and drop not for a final application but for a library and, hence, having side effects outside of the domain of the library does not seem a good idea.

By the way that's just my concern but I would also notice a few observations about the tests I did:

First of those is that, tapping on buttons inside draggable containers, that taps got duplicated so I ended up duplicating the desired action.

The other is more an usability consideration you may already know about (but I would brainstorm a little around it): if you make a wide continer draggable (or a bunch of them stacked one after the other) you may end up making scroll impossible.

...one may reason that it's just a bad UX desingn and I shouldn't have made so wide node draggable but, as I said, I'm working on a general purpose libraray and I'm trying to cover as much as use cases as I can.

And I feel that this could be solved by requiring a simple gexture, like a small drag-and-return to the same position before entering to the drag mode.

...that way, if what the user wants is just to scroll the contents, we would only have introduced a slight initial delay which, in turn, could serve to make user notice that there is something draggable underneath.

Again: Don't take me wrong: I'm not asking anyone to implement anything: Just brainstorming in case there could be some fellow also interested in the idea.

If you wanna see both effects you can check following CodePen example:

https://codepen.io/bitifet/pen/JjzWeKQ

(Just tap to the "+" buttons for first caveat and the second one trying to scroll through tapping over any "employee" item).

Regards.
PraiseThank You Pin
Member 139423818-Aug-18 3:55
Member 139423818-Aug-18 3:55 
PraiseShould be standard - lovely and simple Pin
Member 139358182-Aug-18 19:24
Member 139358182-Aug-18 19:24 
PraiseDragDropTouch.js Pin
Member 1358764120-Dec-17 20:02
Member 1358764120-Dec-17 20:02 
BugNot Working Mouse Click Event On That Pin
Member 135098587-Nov-17 23:49
Member 135098587-Nov-17 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.