1/*! 2 * jQuery UI Touch Punch 0.2.3 3 * 4 * Copyright 2011–2014, Dave Furfero 5 * Dual licensed under the MIT or GPL Version 2 licenses. 6 * 7 * Depends: 8 * jquery.ui.widget.js 9 * jquery.ui.mouse.js 10 */ 11(function ($) { 12 13 // Detect touch support 14 $.support.touch = 'ontouchend' in document; 15 16 // Ignore browsers without touch support 17 if (!$.support.touch) { 18 return; 19 } 20 21 var mouseProto = $.ui.mouse.prototype, 22 _mouseInit = mouseProto._mouseInit, 23 _mouseDestroy = mouseProto._mouseDestroy, 24 touchHandled; 25 26 /** 27 * Simulate a mouse event based on a corresponding touch event 28 * @param {Object} event A touch event 29 * @param {String} simulatedType The corresponding mouse event 30 */ 31 function simulateMouseEvent (event, simulatedType) { 32 33 // Ignore multi-touch events 34 if (event.originalEvent.touches.length > 1) { 35 return; 36 } 37 38 event.preventDefault(); 39 40 var touch = event.originalEvent.changedTouches[0], 41 simulatedEvent = document.createEvent('MouseEvents'); 42 43 // Initialize the simulated mouse event using the touch event's coordinates 44 simulatedEvent.initMouseEvent( 45 simulatedType, // type 46 true, // bubbles 47 true, // cancelable 48 window, // view 49 1, // detail 50 touch.screenX, // screenX 51 touch.screenY, // screenY 52 touch.clientX, // clientX 53 touch.clientY, // clientY 54 false, // ctrlKey 55 false, // altKey 56 false, // shiftKey 57 false, // metaKey 58 0, // button 59 null // relatedTarget 60 ); 61 62 // Dispatch the simulated event to the target element 63 event.target.dispatchEvent(simulatedEvent); 64 } 65 66 /** 67 * Handle the jQuery UI widget's touchstart events 68 * @param {Object} event The widget element's touchstart event 69 */ 70 mouseProto._touchStart = function (event) { 71 72 var self = this; 73 74 // Ignore the event if another widget is already being handled 75 if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { 76 return; 77 } 78 79 // Set the flag to prevent other widgets from inheriting the touch event 80 touchHandled = true; 81 82 // Track movement to determine if interaction was a click 83 self._touchMoved = false; 84 85 // Simulate the mouseover event 86 simulateMouseEvent(event, 'mouseover'); 87 88 // Simulate the mousemove event 89 simulateMouseEvent(event, 'mousemove'); 90 91 // Simulate the mousedown event 92 simulateMouseEvent(event, 'mousedown'); 93 }; 94 95 /** 96 * Handle the jQuery UI widget's touchmove events 97 * @param {Object} event The document's touchmove event 98 */ 99 mouseProto._touchMove = function (event) { 100 101 // Ignore event if not handled 102 if (!touchHandled) { 103 return; 104 } 105 106 // Interaction was not a click 107 this._touchMoved = true; 108 109 // Simulate the mousemove event 110 simulateMouseEvent(event, 'mousemove'); 111 }; 112 113 /** 114 * Handle the jQuery UI widget's touchend events 115 * @param {Object} event The document's touchend event 116 */ 117 mouseProto._touchEnd = function (event) { 118 119 // Ignore event if not handled 120 if (!touchHandled) { 121 return; 122 } 123 124 // Simulate the mouseup event 125 simulateMouseEvent(event, 'mouseup'); 126 127 // Simulate the mouseout event 128 simulateMouseEvent(event, 'mouseout'); 129 130 // If the touch interaction did not move, it should trigger a click 131 if (!this._touchMoved) { 132 133 // Simulate the click event 134 simulateMouseEvent(event, 'click'); 135 } 136 137 // Unset the flag to allow other widgets to inherit the touch event 138 touchHandled = false; 139 }; 140 141 /** 142 * A duck punch of the $.ui.mouse _mouseInit method to support touch events. 143 * This method extends the widget with bound touch event handlers that 144 * translate touch events to mouse events and pass them to the widget's 145 * original mouse event handling methods. 146 */ 147 mouseProto._mouseInit = function () { 148 149 var self = this; 150 151 // Delegate the touch handlers to the widget's element 152 self.element.bind({ 153 touchstart: $.proxy(self, '_touchStart'), 154 touchmove: $.proxy(self, '_touchMove'), 155 touchend: $.proxy(self, '_touchEnd') 156 }); 157 158 // Call the original $.ui.mouse init method 159 _mouseInit.call(self); 160 }; 161 162 /** 163 * Remove the touch event handlers 164 */ 165 mouseProto._mouseDestroy = function () { 166 167 var self = this; 168 169 // Delegate the touch handlers to the widget's element 170 self.element.unbind({ 171 touchstart: $.proxy(self, '_touchStart'), 172 touchmove: $.proxy(self, '_touchMove'), 173 touchend: $.proxy(self, '_touchEnd') 174 }); 175 176 // Call the original $.ui.mouse destroy method 177 _mouseDestroy.call(self); 178 }; 179 180})(jQuery);