| | 1 | // Excerpted from http://stackoverflow.com/questions/5796109/jquery-drag-and-drop-on-touch-devices-ipad-android |
| | 2 | (function ($) { |
| | 3 | // Detect touch support |
| | 4 | $.support.touch = 'ontouchend' in document; |
| | 5 | // Ignore browsers without touch support |
| | 6 | if (!$.support.touch) { |
| | 7 | return; |
| | 8 | } |
| | 9 | var mouseProto = $.ui.mouse.prototype, |
| | 10 | _mouseInit = mouseProto._mouseInit, |
| | 11 | touchHandled; |
| | 12 | |
| | 13 | function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event |
| | 14 | // Ignore multi-touch events |
| | 15 | if (event.originalEvent.touches.length > 1) { |
| | 16 | return; |
| | 17 | } |
| | 18 | event.preventDefault(); //use this to prevent scrolling during ui use |
| | 19 | |
| | 20 | var touch = event.originalEvent.changedTouches[0], |
| | 21 | simulatedEvent = document.createEvent('MouseEvents'); |
| | 22 | // Initialize the simulated mouse event using the touch event's coordinates |
| | 23 | simulatedEvent.initMouseEvent( |
| | 24 | simulatedType, // type |
| | 25 | true, // bubbles |
| | 26 | true, // cancelable |
| | 27 | window, // view |
| | 28 | 1, // detail |
| | 29 | touch.screenX, // screenX |
| | 30 | touch.screenY, // screenY |
| | 31 | touch.clientX, // clientX |
| | 32 | touch.clientY, // clientY |
| | 33 | false, // ctrlKey |
| | 34 | false, // altKey |
| | 35 | false, // shiftKey |
| | 36 | false, // metaKey |
| | 37 | 0, // button |
| | 38 | null // relatedTarget |
| | 39 | ); |
| | 40 | |
| | 41 | // Dispatch the simulated event to the target element |
| | 42 | event.target.dispatchEvent(simulatedEvent); |
| | 43 | } |
| | 44 | mouseProto._touchStart = function (event) { |
| | 45 | var self = this; |
| | 46 | // Ignore the event if another widget is already being handled |
| | 47 | if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { |
| | 48 | return; |
| | 49 | } |
| | 50 | // Set the flag to prevent other widgets from inheriting the touch event |
| | 51 | touchHandled = true; |
| | 52 | // Track movement to determine if interaction was a click |
| | 53 | self._touchMoved = false; |
| | 54 | // Simulate the mouseover event |
| | 55 | simulateMouseEvent(event, 'mouseover'); |
| | 56 | // Simulate the mousemove event |
| | 57 | simulateMouseEvent(event, 'mousemove'); |
| | 58 | // Simulate the mousedown event |
| | 59 | simulateMouseEvent(event, 'mousedown'); |
| | 60 | }; |
| | 61 | |
| | 62 | mouseProto._touchMove = function (event) { |
| | 63 | // Ignore event if not handled |
| | 64 | if (!touchHandled) { |
| | 65 | return; |
| | 66 | } |
| | 67 | // Interaction was not a click |
| | 68 | this._touchMoved = true; |
| | 69 | // Simulate the mousemove event |
| | 70 | simulateMouseEvent(event, 'mousemove'); |
| | 71 | }; |
| | 72 | mouseProto._touchEnd = function (event) { |
| | 73 | // Ignore event if not handled |
| | 74 | if (!touchHandled) { |
| | 75 | return; |
| | 76 | } |
| | 77 | // Simulate the mouseup event |
| | 78 | simulateMouseEvent(event, 'mouseup'); |
| | 79 | // Simulate the mouseout event |
| | 80 | simulateMouseEvent(event, 'mouseout'); |
| | 81 | // If the touch interaction did not move, it should trigger a click |
| | 82 | if (!this._touchMoved) { |
| | 83 | // Simulate the click event |
| | 84 | simulateMouseEvent(event, 'click'); |
| | 85 | } |
| | 86 | // Unset the flag to allow other widgets to inherit the touch event |
| | 87 | touchHandled = false; |
| | 88 | }; |
| | 89 | mouseProto._mouseInit = function () { |
| | 90 | var self = this; |
| | 91 | // Delegate the touch handlers to the widget's element |
| | 92 | self.element |
| | 93 | .on('touchstart', $.proxy(self, '_touchStart')) |
| | 94 | .on('touchmove', $.proxy(self, '_touchMove')) |
| | 95 | .on('touchend', $.proxy(self, '_touchEnd')); |
| | 96 | |
| | 97 | // Call the original $.ui.mouse init method |
| | 98 | _mouseInit.call(self); |
| | 99 | }; |
| | 100 | })(jQuery); |
| | 101 | No newline at end of file |