From 9a5f23ec217c90331511c7ffff5c9f0d507eb9c2 Mon Sep 17 00:00:00 2001 From: Thomas Fuchs Date: Mon, 25 Nov 2013 13:11:28 -0500 Subject: [PATCH] Support IE11 touch events, closes #854 and #860. IE11 no longer supports older (IE10) "MSPointerEvents", going with vendor-prefix less "pointerevents" instead. --- src/touch.js | 34 ++++++++++++++++++++++------------ test/touch.html | 31 ++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/touch.js b/src/touch.js index 816c9e652..6d0bb419d 100644 --- a/src/touch.js +++ b/src/touch.js @@ -36,11 +36,18 @@ } function isPrimaryTouch(event){ - return event.pointerType == event.MSPOINTER_TYPE_TOUCH && event.isPrimary + return (event.pointerType == 'touch' || + event.pointerType == event.MSPOINTER_TYPE_TOUCH) + && event.isPrimary + } + + function isPointerEventType(e, type){ + return (e.type == 'pointer'+type || + e.type.toLowerCase() == 'mspointer'+type) } $(document).ready(function(){ - var now, delta, deltaX = 0, deltaY = 0, firstTouch + var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType if ('MSGesture' in window) { gesture = new MSGesture() @@ -56,9 +63,10 @@ touch.el.trigger('swipe'+ swipeDirectionFromVelocity) } }) - .on('touchstart MSPointerDown', function(e){ - if(e.type == 'MSPointerDown' && !isPrimaryTouch(e)) return; - firstTouch = e.type == 'MSPointerDown' ? e : e.touches[0] + .on('touchstart MSPointerDown pointerdown', function(e){ + if((_isPointerType = isPointerEventType(e, 'down')) && + !isPrimaryTouch(e)) return + firstTouch = _isPointerType ? e : e.touches[0] if (e.touches && e.touches.length === 1 && touch.x2) { // Clear out touch movement data if we have it sticking around // This can occur if touchcancel doesn't fire due to preventDefault, etc. @@ -76,11 +84,12 @@ touch.last = now longTapTimeout = setTimeout(longTap, longTapDelay) // adds the current touch contact for IE gesture recognition - if (gesture && e.type == 'MSPointerDown') gesture.addPointer(e.pointerId); + if (gesture && _isPointerType) gesture.addPointer(e.pointerId); }) - .on('touchmove MSPointerMove', function(e){ - if(e.type == 'MSPointerMove' && !isPrimaryTouch(e)) return; - firstTouch = e.type == 'MSPointerMove' ? e : e.touches[0] + .on('touchmove MSPointerMove pointermove', function(e){ + if((_isPointerType = isPointerEventType(e, 'move')) && + !isPrimaryTouch(e)) return + firstTouch = _isPointerType ? e : e.touches[0] cancelLongTap() touch.x2 = firstTouch.pageX touch.y2 = firstTouch.pageY @@ -88,8 +97,9 @@ deltaX += Math.abs(touch.x1 - touch.x2) deltaY += Math.abs(touch.y1 - touch.y2) }) - .on('touchend MSPointerUp', function(e){ - if(e.type == 'MSPointerUp' && !isPrimaryTouch(e)) return; + .on('touchend MSPointerUp pointerup', function(e){ + if((_isPointerType = isPointerEventType(e, 'up')) && + !isPrimaryTouch(e)) return cancelLongTap() // swipe @@ -141,7 +151,7 @@ // when the browser window loses focus, // for example when a modal dialog is shown, // cancel all ongoing events - .on('touchcancel MSPointerCancel', cancelAll) + .on('touchcancel MSPointerCancel pointercancel', cancelAll) // scrolling the window indicates intention of the user // to scroll, not tap or swipe, so cancel all ongoing events diff --git a/test/touch.html b/test/touch.html index 37881fc45..83632d305 100644 --- a/test/touch.html +++ b/test/touch.html @@ -40,7 +40,7 @@

Touch tests

// // Zepto's touch module only uses the `pageX/Y` and `target` // properties of the first touch in the `touches` TouchList - function touchEvent(type, element, x, y) { + function emitTouchEvent(type, element, x, y) { var event = document.createEvent('Event'), touch = { pageX: x, pageY: y, target: element } @@ -50,10 +50,11 @@

Touch tests

element.dispatchEvent(event) } + // IE 10, Windows Phone 8 // MSPointer events, same idea, different implementation. // For compatibility accepts the same arguments as `touchEvent` // (touch event names will be mapped to MSPointer event names) - function MSPointerEvent(type, element, x, y) { + function emitMSPointerEvent(type, element, x, y) { var event = document.createEvent('Event'), eventMap = { start: 'Down', move: 'Move', end: 'Up'} @@ -67,6 +68,23 @@

Touch tests

element.dispatchEvent(event) } + // IE 11 + // Pointer events, same idea again, yet different implementation. + // For compatibility accepts the same arguments as `touchEvent` + // (touch event names will be mapped to pointer event names) + function emitPointerEvent(type, element, x, y) { + var event = document.createEvent('Event'), + eventMap = { start: 'down', move: 'move', end: 'up'} + + event.initEvent('pointer'+eventMap[type], true, true) + event.pageX = x + event.pageY = y + event.pointerType = 'touch' + event.isPrimary = true + + element.dispatchEvent(event) + } + function down(element, x, y) { emitEvent('start', element, x, y) } @@ -79,6 +97,7 @@

Touch tests

tests = { setUp: function(){ + emitEvent = this.emitEvent $('
TEST ELEMENT
').appendTo('body') }, @@ -283,11 +302,9 @@

Touch tests

// TODO: test swipes in specific directions } - emitEvent = touchEvent - Evidence('TouchTest', tests) - - emitEvent = MSPointerEvent - Evidence('MSPointerTest', tests) + Evidence('TouchTest', $.extend({ emitEvent: emitTouchEvent }, tests)) + Evidence('MSPointerTest', $.extend({ emitEvent: emitMSPointerEvent }, tests)) + Evidence('PointerTest', $.extend({ emitEvent: emitPointerEvent }, tests)) })()