Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Drag and Drop on touch devices (iPad, Android)

We have a card game website that makes extensive use of jQuery Draggable & Droppable and which has worked nearly flawlessly (when using a mouse) for almost a year.

We would REALLY like to have the site work on touch screen devices, but we cannot seem to get jQuery's drag and especially drop functionality to work reliably.

Dragging works "ok" unless the div being dragged is inside another dom element with any kind of offset, margin, padding, etc. If it is, the dragged element is also offset from the user's finger by a similar amount. May not sound like a big deal, but it makes the interface unusuable.

Dropping just doesn't seem to work.

We've researched various options presented here on SO (will try to update this post with links to some of them if I can), but none work for us.

We've also researched jQuery Mobile but this is still in alpha and even so seems to be more of a framework for making a site emulate the UI of a phone vs what we're looking for.

Most of the SO and Google posts on this topic seem to trail off in late 2010 which makes me think there is an obvious answer that maybe we're just missing.

BTW, the functionality we're looking for is clearly technically possible because the YUI libraries for drag and drop work as expected. Unfortunatly, we can't justtify refactoring the site to switch from jQuery to YUI.

Anyone out there have any ideas? We would settle for a answer that supports only iPad, but it really needs to not require we refactor the existing site.

Thanks!

like image 335
Pat Avatar asked Apr 26 '11 20:04

Pat


People also ask

Does jQuery draggable work on mobile?

jQuery UI wasn't originally written to handle mobile devices. It won't even play nicely with jQuery Mobile. some parts of it may still work well in mobile devices, but anything that has anything to do with dragging will fail.

How do you drag and drop in jQuery?

Using jQuery UI, we can make the DOM(Document Object Model) elements to drag anywhere within the view port. This can be done by clicking on the draggable object by mouse and dragging it anywhere within the view port. If the value of this option is set to false, it will prevent the DOM elements to be dragged .

What is UI draggable?

jQuery UI draggable() method is used to make any DOM element draggable. Once the element is made draggable, you can move it by clicking on it with the mouse and drag it anywhere within the viewport.


1 Answers

Paste this at the beginning of your .js file:

(function ($) {     // Detect touch support     $.support.touch = 'ontouchend' in document;     // Ignore browsers without touch support     if (!$.support.touch) {     return;     }     var mouseProto = $.ui.mouse.prototype,         _mouseInit = mouseProto._mouseInit,         touchHandled;      function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event     // Ignore multi-touch events         if (event.originalEvent.touches.length > 1) {         return;         }     event.preventDefault(); //use this to prevent scrolling during ui use      var touch = event.originalEvent.changedTouches[0],         simulatedEvent = document.createEvent('MouseEvents');     // Initialize the simulated mouse event using the touch event's coordinates     simulatedEvent.initMouseEvent(         simulatedType,    // type         true,             // bubbles                             true,             // cancelable                          window,           // view                                1,                // detail                              touch.screenX,    // screenX                             touch.screenY,    // screenY                             touch.clientX,    // clientX                             touch.clientY,    // clientY                             false,            // ctrlKey                             false,            // altKey                              false,            // shiftKey                            false,            // metaKey                             0,                // button                              null              // relatedTarget                       );      // Dispatch the simulated event to the target element     event.target.dispatchEvent(simulatedEvent);     }     mouseProto._touchStart = function (event) {     var self = this;     // Ignore the event if another widget is already being handled     if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {         return;         }     // Set the flag to prevent other widgets from inheriting the touch event     touchHandled = true;     // Track movement to determine if interaction was a click     self._touchMoved = false;     // Simulate the mouseover event     simulateMouseEvent(event, 'mouseover');     // Simulate the mousemove event     simulateMouseEvent(event, 'mousemove');     // Simulate the mousedown event     simulateMouseEvent(event, 'mousedown');     };      mouseProto._touchMove = function (event) {     // Ignore event if not handled     if (!touchHandled) {         return;         }     // Interaction was not a click     this._touchMoved = true;     // Simulate the mousemove event     simulateMouseEvent(event, 'mousemove');     };     mouseProto._touchEnd = function (event) {     // Ignore event if not handled     if (!touchHandled) {         return;     }     // Simulate the mouseup event     simulateMouseEvent(event, 'mouseup');     // Simulate the mouseout event     simulateMouseEvent(event, 'mouseout');     // If the touch interaction did not move, it should trigger a click     if (!this._touchMoved) {       // Simulate the click event       simulateMouseEvent(event, 'click');     }     // Unset the flag to allow other widgets to inherit the touch event     touchHandled = false;     };     mouseProto._mouseInit = function () {     var self = this;     // Delegate the touch handlers to the widget's element     self.element         .on('touchstart', $.proxy(self, '_touchStart'))         .on('touchmove', $.proxy(self, '_touchMove'))         .on('touchend', $.proxy(self, '_touchEnd'));      // Call the original $.ui.mouse init method     _mouseInit.call(self);     }; })(jQuery); 

Call me in the morning ;) (that's really arrogant, I didn't write this solution although I wish that I had, I'd reference it if I remember where I found it, if anyone know where this code came from please comment and credit that person)

UPDATE: Here you go: This is where I found this

like image 180
Likwid_T Avatar answered Oct 08 '22 20:10

Likwid_T