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!
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.
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 .
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With