diff --git a/packages/ember-touch/lib/system/gesture_manager.js b/packages/ember-touch/lib/system/gesture_manager.js index 94fb582..a142f06 100644 --- a/packages/ember-touch/lib/system/gesture_manager.js +++ b/packages/ember-touch/lib/system/gesture_manager.js @@ -99,6 +99,121 @@ Em.GestureManager = Em.Object.extend({ return this._invokeEvent('touchCancel',evt); }, + /* Taking mouseDown, mouseMove, mouseLeave and mouseUp events and mapping them to + * touchStart, touchMove, touchEnd events. + * Add the necessary properties to the event object for click and make it look + * like touch event object. Then give it to Em.Gesture. + * Refer http://goo.gl/GmQg4K to know more about touch event object. + * */ + /** + Relays mouseDown as touchStart events to all the gesture recognizers to the + specified view + + @return Boolen + */ + mouseDown: function(evt, view) { + /* Set _currentEventProperties to the view to track down the mouse events. + * 1. mouseDown followed by mouseMove can only be considered as touchMove + * 2. targetTouches can only be filled if mouseDown and mouseUp have occurred on the same target + * */ + var currentEventProp = { + "savedTarget": evt.target, + "isTouchStarted": true + }; + view.set("_currentEventProperties", currentEventProp); + + evt = this._convertToTouchObj(evt, view); + return this._invokeEvent('touchStart',evt); + }, + + /** + Relays mouseMove as touchMove events to all the gesture recognizers to the + specified view + + @return Boolen + */ + mouseMove: function(evt, view) { + var currentEventProp = view.get("_currentEventProperties"); + // Check if mouseDown event has already been fired in the view and invoke touchMove + if(typeof currentEventProp !== "undefined" && currentEventProp.isTouchStarted) { + evt = this._convertToTouchObj(evt, view); + return this._invokeEvent('touchMove', evt); + } else { + // Do nothing when mouse just hovers on an element + return; + } + }, + + /** + Relays mouseLeave as touchEnd event to all the gesture recognizers to the + specified view + NOTE: mouseLeave should actually be mapped to touchCancel. + Doing so since we have not handled touchCancel anywhere in our views + + @return Boolen + */ + mouseLeave: function(evt, view) { + evt = this._convertToTouchObj(evt, view); + // Clear _currentEventProperties of the view + var currentEventProp = { + "savedTarget": '', + "isTouchStarted": false + }; + view.set("_currentEventProperties", currentEventProp); + + return this._invokeEvent('touchEnd', evt); + }, + + /** + Relays mouseUp as touchEnd events to all the gesture recognizers to the + specified view + + @return Boolen + */ + mouseUp: function(evt, view) { + evt = this._convertToTouchObj(evt, view); + // Clear _currentEventProperties of the view + var currentEventProp = { + "savedTarget": '', + "isTouchStarted": false + }; + view.set("_currentEventProperties", currentEventProp); + + return this._invokeEvent('touchEnd',evt); + }, + + /** Converts click event object into touch event object by adding + * the most needed properties like touches, changedTouches and targetTouches + * Each of these would have clientX, clientY, identifier, pageX, pageY, screenX, screenY, target + * targetTouches will have the event object only if the mouse is in the same target element + * from mouseDown through mouseUp + * @param Object evt Event object of click + * @param Object view Target view. Used to check mouseDown target + * @return Object (touch event object) modified event object + */ + _convertToTouchObj: function(evt, view) { + var touches = [], targetTouches = []; + touches[0] = { + clientX: evt.clientX, + clientY: evt.clientY, + identifier: 0, + pageX: evt.pageX, + pageY: evt.pageY, + screenX: evt.screenX, + screenY: evt.screenY, + target: evt.target + }; + + if(evt.target === view.getPath("_currentEventProperties.savedTarget")) { + // Check if the target element is the same element as in mouseDown + targetTouches = touches; + } + evt.originalEvent.touches = evt.originalEvent.changedTouches = touches; + evt.originalEvent.targetTouches = targetTouches; + + return evt; + }, + /** Relays an event to the gesture recognizers. Used internally by the touch event listeners. Propagates the event to the parentViews.