Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Getting touchy - Everything you (n)ever wanted to know about touch and pointer events / JavaScript Days 2017

Getting touchy - Everything you (n)ever wanted to know about touch and pointer events / JavaScript Days 2017

Beyond smartphones and tablets, touchscreens are finding their way into laptops and even desktop computers. With hardware support for touch becoming increasingly ubiquitous, it's time to explore what new possibilities are available to developers. This session will cover the basics of handling touch events - from making sure simple single-tap interactions are as responsive as possible, all the way to examples of full multitouch, gesture-enabled elements.

Evergreen slidedeck at https://patrickhlauke.github.io/getting-touchy-presentation/ / https://github.com/patrickhlauke/getting-touchy-presentation

357f279672db832fc41a5a2f36559fcb?s=128

Patrick H. Lauke

March 22, 2017
Tweet

Transcript

  1. getting touchy EVERYTHING YOU (N)EVER WANTED TO KNOW ABOUT TOUCH

    AND POINTER EVENTS Patrick H. Lauke / JavaScript Days 2017 / 22 March 2017 / Munich
  2. about me... •  senior accessibility consultant at The Paciello Group

    •  previously developer relations at Opera •  co-editor Touch Events Level 2 •  WG chair and co-editor Pointer Events Level 2
  3. github.com/patrickhlauke/getting-touchy-presentation "evergreen" expanded version of this presentation (and branches for

    specific conferences)
  4. patrickhlauke.github.io/touch

  5. None
  6. Touch/pointer events test results

  7. CodePen: Basic slider - from mouse-only to mouse/touch/stylus enabled

  8. my JavaScript sucks... (but will hopefully convey the right concepts)

  9. “how can I make my website work on touch devices?”

  10. you don't need touch events browsers emulate regular mouse events

  11. patrickhlauke.github.io/touch/tests/event-listener_mouse-only.html

  12. patrickhlauke.github.io/touch/tests/event-listener_mouse-only.html

  13. compatibility mouse events (mouseenter) > mouseover > mousemove* > mousedown

    > (focus) > mouseup > click * only a single “sacrificial” mousemove event fired
  14. on first tap (mouseenter) > mouseover > mousemove > mousedown

    > (focus) > mouseup > click subsequent taps mousemove > mousedown > mouseup > click tapping away (mouseout) > (blur) focus / blur only on focusable elements; subtle differences between browsers Mobile/tablet touchscreen activation/tap event order
  15. emulation works, but is limiting/problematic

  16. 1.  delayed event dispatch 2.  mousemove doesn't track

  17. 1.  delayed event dispatch 2.  mousemove doesn't track

  18. patrickhlauke.github.io/touch/tests/event-listener_show-delay.html less of a problem in modern browsers, but for

    iOS < 9.3 or older Androids still relevant
  19. patrickhlauke.github.io/touch/tests/event-listener_show-delay.html

  20. 1.  delayed event dispatch 2.  mousemove doesn't track

  21. patrickhlauke.github.io/touch/particle/2

  22. patrickhlauke.github.io/touch/particle/2

  23. “we need to go deeper...”

  24. touch events introduced by Apple, adopted in Chrome/Firefox/Opera (and belatedly

    IE/Edge – more on that later) www.w3.org/TR/touch-events
  25. caniuse.com: Can I use touch events?

  26. touchstart touchmove touchend touchcancel

  27. patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html

  28. patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html Bug 128534 - 'mouseenter' mouse compat event not fired...

  29. events fired on tap touchstart > [touchmove]+ > touchend >

    (mouseenter) > mouseover > mousemove > mousedown > (focus) > mouseup > click (mouse events only fired for single-finger tap)
  30. on first tap touchstart > [touchmove]+ > touchend > (mouseenter)

    > mouseover > mousemove > mousedown > (focus) > mouseup > click subsequent taps touchstart > [touchmove]+ > touchend > mousemove > mousedown > mouseup > click tapping away mouseout > (mouseleave) > (blur)
  31. •  too many touchmove events prevent mouse compatibility events after

    touchend (not considered a "clean" tap) •  too many touchmove events on activatable elements can lead to touchcancel (in old Chrome/Browser versions) •  not all browsers consistently send touchmove •  differences in focus / blur and some mouse compatibility events (e.g. mouseenter / mouseleave ) •  some events may only fire when tapping away to another focusable element (e.g. blur ) some browsers outright weird...
  32. Browser/Android 4.3 mouseover > mousemove > touchstart > touchend >

    mousedown > mouseup > click Browser/Blackberry PlayBook 2.0 touchstart > mouseover > mousemove > mousedown > touchend > mouseup > click UC Browser 10.8/Android 6 mouseover > mousemove > touchstart > (touchmove)+ > touchend > mousedown > focus > mouseup > click
  33. Touch/pointer events test results

  34. shouldn't affect your code, unless you're expecting a very specific

    sequence...
  35. <interlude > simple feature detection for touch events

  36. /* feature detection for touch events */ if ( 'ontouchstart'

    in window ) { /* some clever stuff here */ } /* older browsers have flaky support so more hacky tests needed...use Modernizr.touch or similar */
  37. patrickhlauke.github.io/touch/tests/touch-feature-detect.html

  38. /* conditional "touch OR mouse/keyboard" event binding */ if ('ontouchstart'

    in window) { // set up event listeners for touch ... } else { // set up event listeners for mouse/keyboard ... }
  39. don't make it touch-exclusive

  40. hybrid devices touch + mouse + keyboard

  41. None
  42. None
  43. @patrick_h_lauke showing a naive "touch or mouse" issue on Flickr

    (which has since been fixed)
  44. Bug 888304 - touch-events on Firefox-desktop should be disabled until

    we can support them...
  45. Issue 392584: TouchEvent API should be enabled consistently

  46. Chrome now returns window.TouchEvent on non-touch devices patrickhlauke.github.io/touch/tests/touch-feature-detect.html

  47. even on "mobile" we can have multiple inputs...

  48. None
  49. None
  50. Windows 10 "Continuum" (mobile device acting as desktop)

  51. Android + mouse – like touch (mouse emulating touch) touchstart

    > touchend > mouseover > mousemove > mousedown > (focus) > mouseup > click
  52. Android + Chrome 58 + mouse – like desktop mouse

    events (+ pointer events) + click
  53. Blackberry PlayBook 2.0 + mouse – like desktop mouseover >

    mousedown > (mousemove)+ > mouseup > click
  54. Blackberry Leap (BBOS 10.1) + mouse – like desktop mouseover

    > mousedown > (mousemove)+ > mouseup > click
  55. Windows 10 Mobile/Microsoft Edge + mouse – like desktop mouse

    events (+ pointer events) + click
  56. Windows 10 Mobile/Microsoft Edge + keyboard – like desktop focus

    / click / blur
  57. Android + keyboard – like desktop focus / click /

    blur
  58. iOS keyboard only works in same situations as on-screen keyboard

    (e.g. text inputs, URL entry)
  59. VoiceOver enables full keyboard access on iOS

  60. iOS + keyboard – similar to touch (using VO +

    SPACE ) focus / touchstart > touchend > (mouseenter) > mouseover > mousemove > mousedown > blur > mouseup > click
  61. iOS + keyboard – like desktop (using ENTER ) focus

    / click / blur
  62. mobile Assistive Technologies (e.g. screen readers on touchscreen devices)

  63. iOS + VoiceOver (with/without keyboard) – similar to touch focus

    / touchstart > touchend > (mouseenter) > mouseover > mousemove > mousedown > blur > mouseup > click
  64. Android 4.3/Chrome + TalkBack – keyboard/mouse hybrid focus / blur

    > mousedown > mouseup > click > focus
  65. Android 6.1/Chrome + TalkBack – like touch touchstart > touchend

    > mouseover > mouseenter > mousemove > mousedown > focus > mouseup > click
  66. Android 6.1/Firefox + TalkBack – similar to touch touchstart >

    mousedown > focus > touchend > mouseup > click
  67. further scenarios? •  desktop with external touchscreen •  touchscreen laptop

    with non-touch second screen •  touchscreen laptop with trackpad/mouse •  ...and other permutations?
  68. note on trackpad gestures •  trackpads that allow multi-finger gestures

    (e.g. recent MacBooks, Magic Mouse/Trackpad, Windows precision trackpad, ASUS Smart Gesture, Wacom Intuos Pro gestures etc) don't fire touch events / expose touch points •  these gestures are handled directly by the OS/driver and don't reach the browser as raw touches •  Wacom Intuos Pro touch input exposed as mouse to OS •  OS X/Safari 9.1+ does fire Apple's proprietary gesture* events (for pinch-to-zoom, rotation)
  69. no way to detect these cases...

  70. Modernizr.touch detects touch events not touch devices

  71. Modernizr: Detecting a mouse user

  72. Stu Cox: You can't detect a touchscreen

  73. hacks.mozilla.org - Detecting touch [...]

  74. /* feature detection for touch events */ if ('ontouchstart' in

    window) { /* browser supports touch events but user is not necessarily using touch (exclusively) */ /* it could be a mobile, tablet, desktop, fridge ... */ }
  75. touch or mouse or keyboard

  76. touch and mouse and keyboard

  77. what about CSS4 Media Queries?

  78. W3C Media Queries Level 4 (Editor's Draft)

  79. Interaction Media Features pointer / hover relate to “primary” pointing

    device any-pointer / any-hover relate to all pointing devices /* the primary input is ... */ @media (pointer: fine) { /* a mouse, stylus, ... */ } @media (pointer: coarse) { /* a touchscreen, ... */ } @media (pointer: none) { /* not a pointer (e.g. d-pad) */ } @media (hover: hover) { /* hover-capable */ } @media (hover: none) { /* not hover-capable */ } hover: on-demand / any-hover: on-demand removed in recent drafts
  80. Interaction Media Features pointer / hover relate to “primary” pointing

    device any-pointer / any-hover relate to all pointing devices /* across all detected pointing devices at least one is ... */ @media (any-pointer: fine) { /* a mouse, stylus, ... */ } @media (any-pointer: coarse) { /* a touchscreen, ... */ } @media (any-pointer: none) { /* none of them are pointers */ } @media (any-hover: hover) { /* hover-capable */ } @media (any-hover: none) { /* none of them are hover-capable */ } hover: on-demand / any-hover: on-demand removed in recent drafts
  81. caniuse.com: Can I use interaction media features?

  82. Media Features and JavaScript if (window.matchMedia("(any-pointer:coarse)").matches) { ... } /*

    listen for dynamic changes */ window.matchMedia("(any-pointer:coarse)")↵ .onchange = function(e) { ... } window.matchMedia("(any-pointer:coarse)")↵ .addEventListener("change", function(e) { ... } , false } window.matchMedia("(any-pointer:coarse)")↵ .removeEventListener("change", function(e) { ... } , false }
  83. caniuse.com: Can I use matchMedia ?

  84. dev.opera - Interaction Media Features and their potential (for incorrect

    assumptions)
  85. patrickhlauke.github.io/touch/pointer-hover-any-pointer-any-hover primary input is unchanged (and Chrome/Android required full restart

    – Issue 442418)
  86. /* Naive uses of Interaction Media Features */ @media (pointer:

    fine) { /* primary input has fine pointer precision... so make all buttons/controls small? */ } @media (hover: hover) { /* primary input has hover...so we can rely on it? */ } /* pointer and hover only check "primary" input, but what if there's a secondary input that lacks capabilities? */
  87. /* Better uses of Interaction Media Features */ @media (any-pointer:

    coarse) { /* at least one input has coarse pointer precision... provide larger buttons/controls for touch */ } /* test for *any* "least capable" inputs (primary or not) */ Limitation: [mediaqueries-4] any-hover can't be used to detect mixed hover and non-hover capable pointers. Also, pointer / hover / any-pointer / any-hover don't cover non-pointer inputs (e.g. keyboards) – always assume non-hover-capable inputs @media (any-hover: none) { /* at least one input lacks hover capability... don't rely on it or avoid altogether */ }
  88. detect which input the users is using right now...

  89. GitHub: ten1seven / what-input

  90. Demo: What Input?

  91. if in doubt, offer a way to switch interfaces... or

    just always use a touch-optimised interface
  92. </ interlude >

  93. touch events vs limitations/problems

  94. 1.  delayed event dispatch 2.  mousemove doesn't track

  95. 1.  delayed event dispatch 2.  mousemove doesn't track

  96. patrickhlauke.github.io/touch/tests/event-listener_show-delay.html less of a problem in modern browsers, but for

    iOS < 9.3 or older Androids still relevant
  97. why the delay? double-tap to zoom (mostly anyway)

  98. when does the delay happen?

  99. patrickhlauke.github.io/touch/tests/event-listener.html

  100. patrickhlauke.github.io/touch/tests/event-listener.html

  101. touch / mouse events delay touchstart > [touchmove]+ > touchend

    > [300ms delay] (mouseenter) > mouseover > mousemove > mousedown > (focus) > mouseup > click
  102. “how can we make it feel responsive like a native

    app?”
  103. react to events fired before the 300ms delay...

  104. touchstart for an “immediate” control (e.g. fire/jump button on a

    game)
  105. touchend for a control that fires after finger lifted (but

    this can result in events firing after zoom/scroll)
  106. don't make it touch-exclusive

  107. /* DON'T DO THIS: conditional "touch OR mouse/keyboard" event binding

    */ if ('ontouchstart' in window) { // set up event listeners for touch foo.addEventListener('touchend', ...); ... } else { // set up event listeners for mouse/keyboard foo.addEventListener('click', ...); ... }
  108. patrickhlauke.github.io/touch/tests/event-listener_naive-touch-or-mouse.html

  109. /* DO THIS: doubled-up "touch AND mouse/keyboard" event binding */

    // set up event listeners for touch foo.addEventListener('touchend', ...); // set up event listeners for mouse/keyboard foo.addEventListener('click', ...); /* but this would fire our function twice for touch? */ patrickhlauke.github.io/touch/tests/event-listener_naive-event-doubling.html
  110. /* DO THIS: doubled-up "touch AND mouse/keyboard" event binding */

    // set up event listeners for touch foo.addEventListener('touchend', function(e) { // prevent compatibility mouse events and click e.preventDefault(); ... }); // set up event listeners for mouse/keyboard foo.addEventListener('click', ...); patrickhlauke.github.io/touch/tests/event-listener_naive-event-doubling-fixed.html
  111. preventDefault() kills scrolling, pinch/zoom, etc

  112. apply preventDefault() carefully (just on buttons/links, not entire page)

  113. github.com/ftlabs/fastclick

  114. patrickhlauke.github.io/touch/fastclick YouTube: iOS/Safari 300ms click delay: vanilla Bootstrap and using

    fastclick.js
  115. patrickhlauke.github.io/touch/fastclick/fastclick.html YouTube: iOS/Safari 300ms click delay: vanilla Bootstrap and using

    fastclick.js
  116. browsers working to remove double-tap to zoom delay

  117. non-scalable/zoomable viewport and "double-tap to zoom"

  118. <meta name="viewport" content="user-scalable=no"> patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html

  119. <meta name="viewport" content="user-scalable=no"> patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html

  120. ... content="minimum-scale=1, maximum-scale=1" patrickhlauke.github.io/touch/tests/event-listener_minimum-maximum-scale.html

  121. ... content="minimum-scale=1, maximum-scale=1" patrickhlauke.github.io/touch/tests/event-listener_minimum-maximum-scale.html

  122. Changeset 191072 - Web pages with unscalable viewports shouldn't have

    a single tap delay (from iOS 9.3 onwards)
  123. what about accessibility?

  124. Chrome: Settings > Accessibility > Force enable zoom

  125. Opera: Settings > Force enable zoom

  126. Firefox: Settings > Accessibility > Always enable zoom

  127. Samsung Internet: Internet settings > Manual zoom

  128. "Force enable zoom" reintroduces delay – a fair compromise? patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html

  129. @thomasfuchs - Safari/iOS10beta3 ignores unscalable viewports (no official Apple documentation

    about the change...but the 300ms delay is back)
  130. Windows 10 build 15007 on Mobile ignores unscalable viewports

  131. "mobile optimised" viewport and "double-tap to zoom"

  132. Chrome 32+ / Android: content="width=device-width" suppresses double-tap-to-zoom, still allows pinch

    zoom Google Developers: 300ms tap delay, gone away
  133. Bug 941995 - Remove 300ms [...] on "responsive" pages [RESOLVED

    FIXED]
  134. Bug 150604 - Implement viewport-width-based fast-click heuristic (from iOS 9.3

    onwards)
  135. Bug 151077 - Fast-clicking should trigger when scale is equal

    to explicitly set initial scale (from iOS 9.3 onwards)
  136. WebKit blog: More Responsive Tapping on iOS

  137. patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay

  138. suppressing 300ms delay if your code does rely on handling

    click / mouse events: •  "mobile optimised" <meta name="viewport" content="width=device-width"> •  add touch-action:manipulation in CSS (part of Pointer Events) •  use helper library like fastclick.js for older browsers •  make your viewport non-scalable...
  139. 1.  delayed event dispatch 2.  mousemove doesn't track

  140. patrickhlauke.github.io/touch/particle/2

  141. patrickhlauke.github.io/touch/particle/2

  142. events fired on tap touchstart > [touchmove]+ > touchend >

    (mouseenter) > mouseover > mousemove* > mousedown > (focus) > mouseup > click * mouse event emulation fires only a single mousemove too many touchmove events prevent mouse compatibility events after touchend
  143. doubling up handling of mousemove and touchmove

  144. var posX, posY; function positionHandler(e) { posX = e.clientX ;

    posY = e.clientY ; } canvas.addEventListener(' mousemove ', positionHandler, false);
  145. var posX, posY; function positionHandler(e) { posX = e.clientX ;

    posY = e.clientY ; } canvas.addEventListener(' mousemove ', positionHandler, false); canvas.addEventListener(' touchmove ', positionHandler, false); /* but this won't work for touch... */
  146. interface MouseEvent : UIEvent { readonly attribute long screenX ;

    readonly attribute long screenY ; readonly attribute long clientX ; readonly attribute long clientY ; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute unsigned short button; readonly attribute EventTarget relatedTarget; // [DOM4] UI Events readonly attribute unsigned short buttons; }; www.w3.org/TR/DOM-Level-2-Events/events.html#Events-MouseEvent www.w3.org/TR/uievents/#events-mouseevents
  147. partial interface MouseEvent { readonly attribute double screenX; readonly attribute

    double screenY; readonly attribute double pageX ; readonly attribute double pageY ; readonly attribute double clientX; readonly attribute double clientY; readonly attribute double x ; readonly attribute double y ; readonly attribute double offsetX ; readonly attribute double offsetY ; }; www.w3.org/TR/cssom-view/#extensions-to-the-mouseevent- interface
  148. interface TouchEvent : UIEvent { readonly attribute TouchList touches ;

    readonly attribute TouchList targetTouches ; readonly attribute TouchList changedTouches ; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; }; www.w3.org/TR/touch-events/#touchevent-interface
  149. interface Touch { readonly attribute long identifier; readonly attribute EventTarget

    target; readonly attribute long screenX ; readonly attribute long screenY ; readonly attribute long clientX ; readonly attribute long clientY ; readonly attribute long pageX ; readonly attribute long pageY ; }; www.w3.org/TR/touch-events/#touch-interface
  150. TouchList differences touches all touch points on screen targetTouches all

    touch points that started on the element changedTouches touch points that caused the event to fire
  151. changedTouches depending on event: •  for touchstart , all new

    touch points that became active •  for touchmove , all touch points that changed/moved since last event •  for touchend / touchcancel , touch points that were removed (and are not active anymore at this point)
  152. patrickhlauke.github.io/touch/touchlist-objects

  153. var posX, posY; function positionHandler(e) { if ((e.clientX)&&(e.clientY)) { posX

    = e.clientX; posY = e.clientY; } else if (e.targetTouches) { posX = e.targetTouches[0].clientX; posY = e.targetTouches[0].clientY; e.preventDefault() ; } } canvas.addEventListener('mousemove', positionHandler, false ); canvas.addEventListener('touchmove', positionHandler, false );
  154. TouchList collections order •  order of individual Touch objects in

    a TouchList can change •  e.g. targetTouches[0] not guaranteed to always be the same finger when dealing with multitouch •  not problematic for single-finger interactions, but use identifier property for each Touch to explicitly track a particular touch point / finger in multitouch
  155. patrickhlauke.github.io/touch/particle/3

  156. patrickhlauke.github.io/touch/particle/4a

  157. patrickhlauke.github.io/touch/paranoid_0.5 www.splintered.co.uk/experiments/archives/paranoid_0.5

  158. patrickhlauke.github.io/touch/picture-slider

  159. implicit capture •  touch events have implicit capture: once you

    start a touch movement on an element, events keep firing to the element even when moving outside the element's boundaries •  compare to mouse events, which require tricks to track mouse
  160. (3) Naive mouse-driven fake slider (doesn't "capture") Demo: without tricks,

    slider won't work when moving mouse outside
  161. (4) Basic mouse-driven fake slider Exercise/demo: expand mouse-driven code to

    also work with touch
  162. (5) Basic mouse- and touch-driven fake slider

  163. tracking finger movement over time ... swipe gestures

  164. patrickhlauke.github.io/touch/swipe

  165. patrickhlauke.github.io/touch/swipe

  166. /* Swipe detection from basic principles */ Δt = end.time

    - start.time; Δx = end.x - start.x; Δy = end.y - start.y; if (( Δt > timeThreshold ) || ( (Δx + Δy) < distanceThreshold )) { /* too slow or movement too small */ } else { /* it's a swipe! - use Δx and Δy to determine direction - pythagoras √( Δx² + Δy² ) for distance - distance/Δt to determine speed */ }
  167. don't forget mouse/keyboard!

  168. bradfrostweb.com/demo/mobile-first

  169. touchmove fires...a lot!

  170. do absolute minimum on each touchmove (usually: store coordinates)

  171. do heavy lifting (drawing etc.) separately, avoid queueing (e.g. using

    setTimeout and/or requestAnimationFrame )
  172. debounce / throttle events

  173. GitHub: m-gagne / limit.js

  174. Function.prototype.debounce = function (milliseconds, context) { var baseFunction = this,

    timer = null, wait = milliseconds; return function () { var self = context || this, args = arguments; function complete() { baseFunction.apply(self, args); timer = null; } if (timer) { clearTimeout(timer); } timer = setTimeout(complete, wait); }; }; window.addEventListener('touchmove', myFunction.debounce(250) );
  175. Function.prototype.throttle = function (milliseconds, context) { var baseFunction = this,

    lastEventTimestamp = null, limit = milliseconds; return function () { var self = context || this, args = arguments, now = Date.now(); if (!lastEventTimestamp || now - lastEventTimestamp >= limit) { lastEventTimestamp = now; baseFunction.apply(self, args); } }; }; window.addEventListener('touchmove', myFunction.throttle(250) );
  176. patrickhlauke.github.io/touch/touch-limit

  177. why stop at a single point? multitouch support

  178. interface TouchEvent : UIEvent { readonly attribute TouchList touches ;

    readonly attribute TouchList targetTouches ; readonly attribute TouchList changedTouches ; readonly attribute boolean altKey; readonly attribute boolean metaKey; readonly attribute boolean ctrlKey; readonly attribute boolean shiftKey; }; www.w3.org/TR/touch-events/#touchevent-interface
  179. /* iterate over relevant TouchList */ for (i=0; i< e.targetTouches

    .length; i++) { ... posX = e.targetTouches[i].clientX ; posY = e.targetTouches[i].clientY ; ... }
  180. patrickhlauke.github.io/touch/tracker/multi-touch-tracker.html

  181. iOS/iPad preventDefault() can't override 4-finger gestures

  182. iOS7+ Safari/WebView preventDefault() can't override edge swipes

  183. YouTube: iOS/Safari (iPhone) can't prevent edge swipe gestures

  184. Chrome/iOS (WebView) custom swipe, also can't be prevented patrickhlauke.github.io/touch/tracker/multi-touch-tracker.html

  185. multitouch gestures

  186. /* iOS/Safari/WebView has gesture events for size/rotation, not part of

    the W3C Touch Events spec */ /* gesturestart / gesturechange / gestureend */ foo.addEventListener('gesturechange', function(e) { /* e.scale e.rotation */ /* values can be plugged directly into CSS transforms etc */ }); /* not supported in other browsers, but potentially useful for iOS exclusive content (hybrid apps/webviews) */ iOS Developer Library - Safari Web Content Guide - Handling gesture events
  187. patrickhlauke.github.io/touch/iosgestures

  188. patrickhlauke.github.io/touch/iosgestures/image.html

  189. /* Pinch/rotation detection from basic principles */ Δx = x2

    - x1; Δy = y2 - y1; /* pythagoras √( Δx² + Δy² ) to calculate distance */ Δd = Math.sqrt( (Δx * Δx) + (Δy * Δy) ); /* trigonometry to calculate angle */ α = Math.atan2( Δy, Δx ); Mozilla Developer Network: Math.atan2()
  190. patrickhlauke.github.io/touch/pinch-zoom-rotate

  191. patrickhlauke.github.io/touch/picture-organiser

  192. not all old/cheap devices/OSs support multitouch!

  193. HTC Hero – Android 2.1

  194. LG Optimus 2X – Android 2.3.7

  195. ZTE Open – Firefox OS 1.1

  196. Touch Events specification grey areas...

  197. do touch events fire during scroll/zoom?

  198. different models and behaviours, particularly in old browsers YouTube: Touch

    Events and scrolling/zooming (playlist)
  199. e.g. older versions of Chrome fire touchcancel on scroll/zoom YouTube:

    Google Developers - Mobile Web Thursdays: Performance on Mobile
  200. not defined in spec (yet), but de facto yes in

    most modern browsers patrickhlauke.github.io/touch/gesture-touch
  201. touchmove and scroll •  useful for common interactions like pull

    to refresh – let browser (over)scroll and track movement •  has scroll performance impact, as browser is blocked on event listener in case it cancels the scroll (see passive event listeners)
  202. non-standard iOS quirks...

  203. making generic elements clickable...

  204. Historically (until end of 2016?), Apple suggested adding dummy onclick=""

    handlers iOS Developer Library - Safari Web Content Guide - Handling Events
  205. dummy onclick="" handlers are unnecessary (at least since iOS6) Apple

    quietly dropped this from their documentation... patrickhlauke.github.io/touch/ios-clickable/
  206. mouse + click event bubbling on touch (important when using

    event delegation)
  207. Quirksmode: Mouse event bubbling in iOS

  208. patrickhlauke.github.io/touch/bubbling/button.html

  209. patrickhlauke.github.io/touch/bubbling/link.html

  210. patrickhlauke.github.io/touch/bubbling/div.html

  211. patrickhlauke.github.io/touch/bubbling/div-onclick-target.html

  212. patrickhlauke.github.io/touch/bubbling/div-onclick-ancestor.html

  213. patrickhlauke.github.io/touch/bubbling/div-addeventlistener-target.html

  214. patrickhlauke.github.io/touch/bubbling/div-addeventlistener-ancestor.html

  215. patrickhlauke.github.io/touch/bubbling/div-cursorpointer-target.html

  216. patrickhlauke.github.io/touch/bubbling/div-cursorpointer-ancestor.html

  217. mouse + click bubbling in iOS •  target element is

    a link or form control •  target or any ancestor (up to but not including body ) has explicit mouse or click handler (even if only empty function) •  target or any ancestor (up to and including document ) has cursor:pointer Quirksmode: Mouse event bubbling in iOS
  218. iOS quirks in a nutshell if your code does rely

    on handling mouse events: •  you don't need dummy click handlers to make arbitrary (non- interactive) elements react to mouse events (such as mouseover , mousedown , mouseup ...) •  you do need to do extra work if you rely on event bubbling / event delegation of mouse events (including click )
  219. Touch Events extensions...

  220. W3C Touch Events Extensions WG Note

  221. /* Extension to touch objects */ partial interface Touch {

    readonly attribute float radiusX; readonly attribute float radiusY; readonly attribute float rotationAngle; readonly attribute float force; };
  222. Google Developers: Using rotationAngle and touchRadius

  223. /* Touch Events – contact geometry */ partial interface Touch

    { readonly attribute float radiusX ; readonly attribute float radiusY ; readonly attribute float rotationAngle ; readonly attribute float force; };
  224. patrickhlauke.github.io/touch/tracker/tracker-radius-rotationangle.html YouTube: Touch Events: radiusX, radiusY and rotationAngle

  225. Rick Byers - Paint (with rotationAngle and touchRadius)

  226. /* Touch Events – force */ partial interface Touch {

    readonly attribute float radiusX; readonly attribute float radiusY; readonly attribute float rotationAngle; readonly attribute float force ; }; force : value in range 0 – 1 . if no hardware support 0 (some devices, e.g. Nexus 10, "fake" force based on radiusX / radiusY )
  227. patrickhlauke.github.io/touch/tracker/tracker-force-pressure.html iPhone 6s with 3D Touch supports force ... (Safari

    and WKWebView, e.g. Chrome/iOS, but not UIWebView, e.g. Firefox/iOS)
  228. patrickhlauke.github.io/touch/tracker/tracker-force-pressure.html ...while in non-3D Touch models (e.g. iPhone 5c) force

    == 0
  229. 3D Touch ≠ Force Touch •  Force Touch is Apple's

    proprietary extension to mouse events •  only aimed at force-enabled trackpads (new Apple models) •  new events: webkitmouseforcewillbegin , webkitmouseforcedown , webkitmouseforceup , webkitmouseforcechanged •  mouse events have additional webkitForce property Safari Developer Library: Responding to Force Touch Events
  230. Google Developers: Precision Touch for Precise Gestures

  231. Bug 133180 - Touch events should allow for device-pixel accuracy

  232. interface Touch { readonly attribute long identifier; readonly attribute EventTarget

    target; readonly attribute long float screenX; readonly attribute long float screenY; readonly attribute long float clientX; readonly attribute long float clientY; readonly attribute long float pageX; readonly attribute long float pageY; };
  233. W3C Touch Events Community Group

  234. W3C Web Events WG - Touch Events errata (early effort

    to clarify grey areas, simplify language used)
  235. W3C Touch Events Level 2 (Editor's Draft) (merges errata, touch

    events extensions, fractional touch coordinates)
  236. Pointer Events

  237. up to IE9 (Win7 / WinPhone7.5) only mouse events

  238. in IE10 Microsoft introduced Pointer Events

  239. unifies mouse, touch and pen input into a single event

    model
  240. ...and some new inputs (though currently mapped to mouse) Building

    Xbox One Apps using HTML and JavaScript YouTube: Xbox One Edge Browser sends Pointer Events
  241. not just some “not invented here” technology

  242. submitted by Microsoft as W3C Candidate REC 09 May 2013

  243. Pointer Events - W3C REC 24 February 2015

  244. work now continues to enhance/expand Pointer Events... W3C Pointer Events

    Level 2 (Editor's Draft)
  245. caniuse.com: Can I use pointer events?

  246. Bug 822898 - Implement pointer events

  247. about:config / dom.w3c_pointer_events.enabled

  248. ...what about Apple?

  249. Microsoft submitted a proof of concept WebKit patch html5labs.interoperabilitybridges.com/prototypes/...

  250. Bug 105463 - Implement pointer events RESOLVED WONTFIX

  251. Maciej Stachowiak - [webkit-dev] pointer events specification - first editors

    draft
  252. @patrick_h_lauke paraphrasing Apple's stance on Pointer Events...

  253. None
  254. Apple Pencil currently indistinguishable from touch in browser / JavaScript

    (no tilt information, fires touch events)
  255. the anatomy of Pointer Events (sequence, event object, ...)

  256. patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html

  257. events fired on tap (Edge) mousemove* > pointerover > mouseover

    > pointerenter > mouseenter > pointerdown > mousedown > focus gotpointercapture > pointermove > mousemove > pointerup > mouseup > lostpointercapture > click > pointerout > mouseout > pointerleave > mouseleave mouse events fired “inline” with pointer events (for a primary pointer, e.g. first finger on screen)
  258. IE10/IE11 quirks •  vendor-prefixed in IE10 ( MSPointerDown ..., navigator.msMaxTouchPoints

    , -ms-touch-action ) •  unprefixed in IE11 (but prefixed versions mapped for compatibility) •  event order (when click is fired) incorrect in IE10/IE11 see W3C Pointer Events WG mailing list - Jacob Rossi (Microsoft)
  259. Chrome, Edge (on mobile), IE11 (Windows Phone 8.1update1) support both

    Touch Events and Pointer Events w3c.github.io/pointerevents/#mapping-for-devices-that-do-not-support-hover
  260. patrickhlauke.github.io/touch/tests/event-listener_all-no-timings.html

  261. about:flags in Microsoft Edge to turn on touch events on

    desktop (e.g. touch-enabled laptops) – off by default for site compatibility
  262. ... when touch events also supported (Edge) pointerover > pointerenter

    > pointerdown > touchstart > pointerup > touchend > mouseover > mouseenter > mousemove > mousedown > focus > mouseup > click > pointerout > pointerleave Specific order of events is not defined in the spec in this case – will vary between browsers... only problem if handling both pointer events and mouse events (which is nonsensical)
  263. /* Pointer Events extend Mouse Events vs Touch Events and

    their new objects / TouchLists / Touches */ interface PointerEvent : MouseEvent { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure; readonly attribute float tangentialPressure; /* Level 2 */ readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; /* Level 2 */ readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; }
  264. handling mouse input is exactly the same as traditional mouse

    events (only change pointer* instead of mouse* event names)
  265. handling touch or stylus is also exactly the same as

    traditional mouse events (mouse code can be adapted to touch/stylus quickly)
  266. simple feature detection for pointer events

  267. /* detecting pointer events support */ if ( window.PointerEvent )

    { /* some clever stuff here but this covers touch, stylus, mouse, etc */ } /* still listen to click for keyboard! */
  268. "don't forget about keyboard users" note in Pointer Events spec

  269. /* detect maximum number of touch points */ if (

    navigator.maxTouchPoints > 0 ) { /* device with a touchscreen */ } if ( navigator.maxTouchPoints > 1 ) { /* multitouch-capable device */ } "you can detect a touchscreen" ...but user may still use other input mechanisms
  270. patrickhlauke.github.io/touch/tests/pointer-multitouch-detect.html

  271. do pointer events fire during scroll/zoom?

  272. w3c.github.io/pointerevents/#the-pointercancel-event

  273. once a browser handles scrolling, it sends pointercancel patrickhlauke.github.io/touch/gesture-touch/pointerevents.html

  274. pointer events vs limitations/problems of mouse event emulation

  275. 1.  delayed event dispatch 2.  mousemove doesn't track

  276. 1.  delayed event dispatch 2.  mousemove doesn't track

  277. patrickhlauke.github.io/touch/tests/event-listener.html (IE11/WinPhone 8.1 Update no optimization for width=device-width )

  278. patrickhlauke.github.io/touch/tests/event-listener.html (IE/Win8 has double-tap to zoom, so problem on desktop

    too)
  279. patrickhlauke.github.io/touch/tests/event-listener.html (Microsoft Edge/Win10 has double-tap to zoom, so problem on

    desktop too)
  280. pointer / mouse events and delay ... [300ms delay] click

    ... 300ms delay just before click event
  281. “how can we make it feel responsive like a native

    app?”
  282. we could try a similar approach to touch events...

  283. •  double-up pointerup and click listeners? •  prevent code firing

    twice with preventDefault ? won't work: preventDefault() stops mouse compatibility events, but click is not considered mouse compatibility event
  284. patrickhlauke.github.io/touch/tests/event-listener.html

  285. a more declarative approach with touch-action

  286. touch-action what action should the browser handle? touch-action: auto /*

    default */ touch-action: none touch-action: pan-x touch-action: pan-y touch-action: manipulation /* pan/zoom */ touch-action: pan-x pan-y /* can be combined */ www.w3.org/TR/pointerevents/#the-touch-action-css-property only determines default touch action, does not stop compatibility mouse events nor click
  287. Pointer Events Level 2 expanded set of values (useful for

    pull-to-refresh, carousels, etc) touch-action: pan-left touch-action: pan-right touch-action: pan-up touch-action: pan-down touch-action: pan-left pan-down /* can be combined */ touch-action: pan-x pan-down /* can be combined */ w3c.github.io/pointerevents/#the-touch-action-css-property new values only determine allowed pan direction at the start of the interaction; once panning starts, user can also move in opposite direction along same axis
  288. compat.spec.whatwg.org adds extra value pinch-zoom

  289. patrickhlauke.github.io/touch/touch-action-scrolling

  290. although it's called "touch-action", it applies to any pointer type

    that pans/zooms (e.g. Samsung Note + stylus, Chrome <58/Android + mouse) w3c.github.io/pointerevents/#declaring-candidate-regions-for-default-touch-behaviors
  291. touch-action:none (suppress all default browser behaviour)

  292. patrickhlauke.github.io/touch/tests/event-listener_touch[...]

  293. patrickhlauke.github.io/touch/tests/event-listener_touch[...]

  294. touch-action:none kills scrolling, long-press, pinch/zoom

  295. touch-action:manipulation (suppress double-tap-to-zoom)

  296. patrickhlauke.github.io/touch/tests/event-listener_touch[...]

  297. patrickhlauke.github.io/touch/tests/event-listener_touch[...]

  298. caniuse.com: Can I use touch-action?

  299. browsers working to remove double-tap to zoom delay (when page

    not zoomable)
  300. <meta name="viewport" content="user-scalable=no"> patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html

  301. None
  302. "Allow zooming on all web content" reintroduces delay patrickhlauke.github.io/touch/tests/event-listener_user-scalable-no.html

  303. "Allow zooming..." option currently missing in Win 10 Mobile

  304. Windows 10 build 15007 on Mobile ignores unscalable viewports no

    delay until user zooms for first time...
  305. width=device-width still has delay in IE11/WinPhone 8.1 Update patrickhlauke.github.io/touch/tests/event-listener_width-device-width.html

  306. Microsoft Edge removes delay for width=device-width patrickhlauke.github.io/touch/tests/event-listener_width-device-width.html

  307. patrickhlauke.github.io/touch/tests/results/#suppressing-300ms-delay

  308. 1.  delayed event dispatch 2.  mousemove doesn't track

  309. patrickhlauke.github.io/touch/particle/2 mousemove / pointermove fire, but browser scroll action takes

    over
  310. you can "fake" it with touch-action:none and listen for mouse

    events...
  311. patrickhlauke.github.io/touch/particle/2a (does not work in Microsoft Edge/Windows 10 Mobile due

    to touch events support)
  312. better: just listen to pointermove...

  313. no need for separate mouse or touch event listeners

  314. /* touch events: separate handling */ foo.addEventListener('touchmove', ... , false);

    foo.addEventListener('mousemove', ... , false); /* pointer events: single listener for mouse, stylus, touch */ foo.addEventListener(' pointermove ', ... , false);
  315. no need for separate mouse or touch code to get

    x / y coords
  316. /* Reminder: Touch Events need separate code for x /

    y coords */ function positionHandler(e) { if ((e.clientX)&&(e.clientY)) { posX = e.clientX; posY = e.clientY; } else if (e.targetTouches) { posX = e.targetTouches[0].clientX; posY = e.targetTouches[0].clientY; ... } } canvas.addEventListener('mousemove', positionHandler, false ); canvas.addEventListener('touchmove', positionHandler, false );
  317. /* Pointer Events extend Mouse Events */ foo.addEventListener(' pointermove ',

    function(e) { ... posX = e.clientX ; posY = e.clientY ; ... }, false); www.w3.org/TR/pointerevents/#pointerevent-interface
  318. 3D Rotator by Creative Punch coded to only use mouse

    events
  319. 3D Rotator modified to use Pointer Events minimal code changes,

    as Pointer Events extend mouse events
  320. (4) Basic mouse-driven fake slider Exercise/demo: convert mouse-driven code to

    use Pointer Events
  321. (6) Basic pointer events-driven fake slider

  322. but you can distinguish mouse or touch or stylus

  323. foo.addEventListener('pointermove', function(e) { ... switch( e.pointerType ) { case '

    mouse ': ... break; case ' pen ': ... break; case ' touch ': ... break; default : /* future-proof */ } ... } , false);
  324. /* in IE11/Edge, pointerType returns a string in IE10, the

    return type is long */ MSPOINTER_TYPE_TOUCH: 0x00000002 MSPOINTER_TYPE_PEN: 0x00000003 MSPOINTER_TYPE_MOUSE: 0x00000004 MSDN: IE Dev Center - API reference - pointerType property
  325. what about multitouch?

  326. /* PointerEvents don't have the handy TouchList objects, so we

    have to replicate something similar... */ var points = []; switch (e.type) { case ' pointerdown ': /* add to the array */ break; case ' pointermove ': /* update the relevant array entry's x and y */ break; case ' pointerup ': case ' pointercancel ': /* remove the relevant array entry */ break; }
  327. patrickhlauke.github.io/touch/tracker/multi-touch-tracker-pointer.html (note multiple isPrimary pointers, per pointer type)

  328. patrickhlauke.github.io/touch/tracker/multi-touch-tracker-pointer-hud.html

  329. simultaneous use of inputs is hardware-dependent (e.g. Surface 3 "palm

    blocking" prevents concurrent touch/stylus/mouse, but not touch/external mouse/external stylus)
  330. YouTube: Pointer Events support multiple stylus/pen inputs simultaneously

  331. /* like iOS/Safari, IE/Edge have higher-level gestures , but these

    are not part of the W3C Pointer Events spec */ foo.addEventListener("MSGestureStart", ... , false) foo.addEventListener("MSGestureEnd", ... , false) foo.addEventListener("MSGestureChange", ... , false) foo.addEventListener("MSInertiaStart", ... , false) foo.addEventListener("MSGestureTap", ... , false) foo.addEventListener("MSGestureHold", ... , false) /* not supported in other browsers, but potentially useful for IE/Edge exclusive content (e.g. UWP packaged/hosted/hybrid web app); for web, replicate these from basic principles again... */ MSDN IE10 Developer Guide: Gesture object and events
  332. extended capabilities (if supported by hardware)

  333. /* Pointer Events - pressure */ interface PointerEvent : MouseEvent

    { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure ; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; } pressure : value in range 0 – 1 . if no hardware support, 0.5 in active button state, 0 otherwise
  334. patrickhlauke.github.io/touch/tracker/... YouTube: Touch tracker with Surface 3 pen

  335. hovering stylus •  hardware-dependant •   pointermove fires •  

    pressure == 0 (non-active button state) •  track pointerdown / pointerup to be safe
  336. /* Pointer Events - contact geometry */ interface PointerEvent :

    MouseEvent { readonly attribute long pointerId; readonly attribute long width ; readonly attribute long height ; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX; readonly attribute long tiltY; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; } if hardware can't detect contact geometry, either 0 or "best guess" (e.g. for mouse/stylus, return width / height of 1 )
  337. patrickhlauke.github.io/touch/tracker/tracker-width-height.html YouTube: Pointer Events width and height ...

  338. patrickhlauke.github.io/touch/tracker/multi-touch-tracker-pointer-hud.html (Nokia Lumia 520: pressure is 0.5 - active state

    - and width / height is 0 )
  339. /* Pointer Events - tilt */ interface PointerEvent : MouseEvent

    { readonly attribute long pointerId; readonly attribute long width; readonly attribute long height; readonly attribute float pressure; readonly attribute float tangentialPressure; readonly attribute long tiltX ; readonly attribute long tiltY ; readonly attribute long twist; readonly attribute DOMString pointerType; readonly attribute boolean isPrimary; } tiltX / tiltY : value in degrees -90 – 90 . returns 0 if hardware does not support tilt
  340. patrickhlauke.github.io/touch/pen-tracker YouTube: ...pen with tilt, pressure and hover support

  341. patrickhlauke.github.io/touch/pen-tracker YouTube: Chrome on Samsung Galaxy Note 4 - Pointer

    Events and stylus
  342. pointermove fires if any property changes, not just x/y position

    ( width , height , tiltX , tiltY , pressure )
  343. pointer capture (implicit vs explicit)

  344. •  touch events have implicit capture: once you start a

    touch movement on an element, events keep firing to the element even when moving outside the element's boundaries •  for mouse / stylus: pointer events like mouse events: only fire events to an element while pointer inside it (but allow explicit capture) •  for touch: pointer events level 2 use implicit capture (for compatibility with touch events) Pointer Events Level 2: Implicit Pointer Capture
  345. /* events related to pointer capture */ foo.addEventListener("gotpointercapture", ... ,

    false) foo.addEventListener("lostpointercapture", ... , false) /* methods related to pointer capture */ element.setPointerCapture(pointerId) element.releasePointerCapture(pointerId) if (element.hasPointerCapture(pointerId)) { ... }
  346. /* example of how to capture a pointer explicitly */

    element.addEventListener('pointerdown', function(e) { this. setPointerCapture(e.pointerId) ; }, false } /* capture automatically released on pointerup / pointercancel or explicitly with releasePointerCapture() */ patrickhlauke.github.io/touch/tests/pointercapture.html
  347. setPointerCapture can simplify mouse input e.g. draggable interfaces/sliders, use instead

    of "bind mousemove to document / body on mousedown "
  348. (6) Basic pointer events-driven fake slider Exercise/demo: simplify code to

    use pointer capture
  349. (7) Basic pointer events-driven fake slider with setPointerCapture

  350. pointer events as the future?

  351. transitional event handling (until all browsers support pointer events)

  352. /* cover all cases (hat-tip Stu Cox) */ if (window.PointerEvent)

    { /* bind to Pointer Events: pointerdown, pointerup, etc */ } else { /* bind to mouse events: mousedown, mouseup, etc */ if ('ontouchstart' in window) { /* bind to Touch Events: touchstart, touchend, etc */ } } /* bind to keyboard / click */
  353. polyfills for pointer events (code for tomorrow, today)

  354. GitHub - jQuery Pointer Events Polyfill (PEP)

  355. /* adding jQuery PEP */ <script src="https://code.jquery.com/pep/0.4.1/pep.js"></script> /* need to

    use custom touch-action attribute, not CSS (yet) */ <button touch-action="none" >...</div>
  356. patrickhlauke.github.io/touch/pep-draw

  357. patrickhlauke.github.io/touch/pep/listener/event-listener.html

  358. events fired on tap with PEP pointerover > pointerenter >

    pointerdown > touchstart > pointerup > pointerout > pointerleave > touchend > mouseover > mouseenter > mousemove > mousedown > mouseup > click essentially, relevant Pointer Events before touchstart and touchend
  359. 3D Rotator modified to use Pointer Events minimal code changes,

    as Pointer Events extend mouse events
  360. 3D Rotator modified to use Pointer Events (and PEP)

  361. (7) Basic pointer events-driven fake slider with setPointerCapture Exercise/demo: make

    slider work in non-Pointer-Events browsers
  362. (8) Basic pointer events-driven fake slider with setPointerCapture and PEP

  363. utility libraries (because life is too short to hand-code gesture

    support)
  364. Hammer.js

  365. Hammer.js

  366. patrickhlauke.github.io/touch/swipe

  367. /* Hammer's high-level events example */ var element = document.getElementById('test_el');

    var hammertime = new Hammer(element); hammertime.on("swipe", function(event) { /* handle horizontal swipes */ });
  368. patrickhlauke.github.io/touch/hammer/swipe

  369. debugging/testing

  370. nothing beats having real devices...

  371. BrowserStack (includes Physical Devices)

  372. None
  373. Chrome DevTools / Remote Debugging Android Devices Chrome DevTools /

    Using the Console / Monitor events
  374. enable touch events even without a touchscreen (to test "naive"

    'ontouchstart' in window code) chrome://flags/#touch-events
  375. Chrome DevTools / Device Mode & Mobile Emulation correctly emulates

    touch and pointer events
  376. Chrome DevTools / Device Mode & Mobile Emulation correctly emulates

    pointer events (with pointerType=="touch" )
  377. emulate a touch interface (even without mobile emulation)

  378. Firefox Developer Tools > Responsive Design Mode correctly emulates touch

    events
  379. no touch emulation, nor touch events + pointer events (like

    on real Windows 10 Mobile) emulation, in Edge/F12 Tools
  380. no touch emulation in Safari "Responsive Design Mode"

  381. bonus material

  382. no concept of hover on touch devices iOS fakes it,

    Samsung Galaxy Note II/Pro + stylus, ...
  383. iOS Developer Library - Safari Web Content Guide - Handling

    Events while this works ok, Safari is the only browser doing it...
  384. YouTube: Samsung Galaxy Note Pro 12.2 stylus hover requires advanced

    stylus, which is uncommon...
  385. MSDN: Hover touch support

  386. Channel9 MSDN - IE11: Using Hover Menus with Touch

  387. MSDN: Using aria-haspopup to simulate hover on touch-enabled devices non-standard

    use of the aria-haspopup attribute...
  388. avoid hover interfaces? arguable ... it's a user experience decision

  389. complement for touch! same considerations as for keyboard users...

  390. Input Device Capabilities (Draft Community Group Report)

  391. Input Device Capabilities •  currently limited usefulness - only has

    firesTouchEvents property •  limited use cases (see Identifying touch events that will trigger a tap / click, Identifying mouse events derived from touch events and Google Developer: Input Device Capabilities) •  easier to switch to Pointer Events (and add PEP)?
  392. myButton.addEventListener('touchstart', addHighlight, false); myButton.addEventListener('touchend', removeHighlight, false); myButton.addEventListener('mousedown', addHighlight, false); myButton.addEventListener('mouseup',

    removeHighlight, false); myButton.addEventListener('click', someFunction, false); /* addHighlight/removeHighlight will fire twice for touch (first for touch, then for mouse compatibility events); can't use e.preventDefault(), as we want to rely on 'click' */
  393. myButton.addEventListener('touchstart', addHighlight, false); myButton.addEventListener('touchend', removeHighlight, false); myButton.addEventListener('mousedown', function(e) { if

    (!e.sourceCapabilities.firesTouchEvents) { addHighlight(e); } } , false); myButton.addEventListener('mouseup', function(e) { if (!e.sourceCapabilities.firesTouchEvents) { removeHighlight(e); } } , false); myButton.addEventListener('click', someFunction, false); /* same function for touch and mouse, but if mouse check if source input fires touch events (i.e. this is a mouse compat event) */
  394. Passive Event Listeners (EventListenerOptions)

  395. Leap Motion Controller

  396. Leap Motion •  requires custom code (JavaScript, Java, C++, ...)

    using proprietary API (e.g. Leap Motion: JavaScript SDK Documentation) •  does not fire touch nor mouse events (third party native apps in Leap Motion App Store available to simulate native mouse) •  (personally find it quite inaccurate and horrible)
  397. /* rough proof of concept that fires programmatic Pointer Events

    for each "pointable" (finger / tool) */ e = new PointerEvent('pointermove', { pointerId: ... , width: ... , height: ... , pressure: ... , tiltX: ... , tiltY: ... , pointerType: 'leap', isPrimary: false, clientX: ... , clientY: ... , screenX: ... , screenY: ... }); /* dispatch event to whatever element is at the coordinates (no support for pointer capture at this stage) */ document.elementFromPoint(x, y).dispatchEvent(e);
  398. YouTube: Leap Motion generating programmatic Pointer Events patrickhlauke.github.io/touch/leapmotion/tracker

  399. further reading...

  400. •  Matt Gaunt – Touch Feedback for Mobile Sites •

     Jonathan Stark – FastActive •  Stephen Woods – HTML5 Touch Interfaces •  YouTube: Stephen Woods – Responsive HTML5 Touch Interfaces •  Chris Wilson + Paul Kinlan – Touch And Mouse: Together Again For The First Time •  Ryan Fioravanti – Creating Fast Buttons for Mobile Web Applications •  Boris Smus – Multi-touch Web Development •  Boris Smus – Generalized input on the cross-device web •  Boris Smus – Interactive touch laptop experiments
  401. •  Rick Byers + Boris Smus (Google I/O) – Point,

    Click, Tap, Touch - Building Multi-Device Web Interfaces •  Grant Goodale – Touch Events •  W3C – Touch Events Extensions •  Mozilla Developer Network – Touch Events •  WebPlatform.org – Pointer Events •  Rick Byers – The best way to avoid the dreaded 300ms click delay is to disable double-tap zoom •  Chromium Issue 152149: All touch-event related APIs should exist if touch support is enabled at runtime
  402. •  Tim Kadlec – Avoiding the 300ms Click Delay, Accessibly

    •  David Rousset - Unifying touch and mouse [...] •  Microsoft – Pointer events updates (differences between IE10-IE11) •  Patrick H. Lauke – Webseiten zum Anfassen •  Patrick H. Lauke – Drei unter einem Dach: Pointer-Events für Maus, Stylus und Touchscreen •  Patrick H. Lauke – Erweiterte Interaktionsmöglichkeiten mit Touchscreens •  Patrick H. Lauke – Make your site work on touch devices •  Stu Cox – You can't detect a touchscreen
  403. •  Microsoft – Hover touch support (IE10/IE11) •  W3C Media

    Queries Level 4 – pointer •  Stu Cox – The Good & Bad of Level 4 Media Queries •  Peter-Paul Koch – Touch table •  Peter-Paul Koch – Preventing the touch default •  Peter-Paul Koch – Mouse event bubbling in iOS •  YouTube: Edge Conference (Feb 2013 London) – Panel: Input •  Edge Conference (Mar 2014 London) – Panel: Pointers and Interactions •  Trent Walton – Device-Agnostic
  404. •  Stu Cox – The Golden Pattern for Handling Touch

    Input •  Matt Gaunt – ‘Focusing’ on the Web Today •  Mobiscroll – Working with touch events •  Peter-Paul Koch – The iOS event cascade and innerHTML •  Patrick H. Lauke – Make your site work on touch devices •  Scott Jehl (Filament Group) – Tappy: A custom tap event handler •  Yehuda Katz – Touch events on the web are fundamentally unfinished •  Google Developers: A More Compatible, Smoother Touch
  405. •  Andrea Giammarchi – PointerEvents No More •  YouTube: Matt

    Gaunt (Google) - Touch in a Web App? No Problem •  Luke Wroblewski – How to Communicate Hidden Gestures •  David Washington - Designing custom touch interactions •  David Washington - Building pull-to-refresh •  Andy Peatling - JavaScript Pull to Refresh for the Web •  Tilo Mitra – The State of Gestures •  YouTube: Tilo Mitra (YUI) – The State of Gestures
  406. •  Rob Larsen - The Uncertain Web: Pointer Event Polyfill

    and Chrome Fragmentation •  Detlev Fisher - Implications of new input modes (touch, speech, gestures) for the Web Content Accessibility Guidelines •  Ralph Thomas - Towards declarative touch interactions •  Windows Dev Center: Windows desktop applications > Guidelines > Interaction (touch, keyboard, mouse, pen) •  Microsoft Open Technologies - jQuery Adopts Pointer Events
  407. •  jQuery blog - Getting on Point •  IEBlog -

    Pointer Events W3C Recommendation, Interoperable Touch, and Removing the Dreaded 300ms Tap Delay •  Microsoft Open Technologies - Pointer Events is now a W3C Standard •  Patrick H. Lauke (The Paciello Group) - Pointer Events advance to W3C Recommendation •  Jacob Rossi - The Input Shouldn't Matter •  hacks.mozilla.org - Pointer Events now in Firefox Nightly
  408. •  Rick Byers – Interoperability Case Studies at BlinkOn 5

    (touch-action) •  Mozilla Developer Network – Pointer Events •  Christian Saylor – A Touch of Brilliance: Why 3D Touch Matters •  Lukas Mathis – Usability on Mobile Is Getting Worse •  Rocket Insights – Initial thoughts on 3D Touch •  Wiser Coder – Disable “pull to refresh” in Chrome for Android
  409. •  Google Developers / Web Fundamentals: Add touch to your

    site •  Alex Gibson – Different ways to trigger touchcancel in mobile browsers •  BBC Global Experience Language: How to design for touch •  Google BlinkOn 5: Lightning talks / Mustaq Ahmed – Pointer Events in Chrome implementation update •  A Book Apart: Josh Clark – Designing for Touch •  Kickstarter – The Sensel Morph: Interaction Evolved
  410. •  Ruadhán O'Donoghue – The HTML5 Pointer Events API: Combining

    touch, mouse, and pen •  Jordan Staniscia – Hover is dead. Long live hover. •  Jason Grigsby – Four Truths About Input •  Jason Grigsby – Adapting to Input •  David Corbacho – Debouncing and Throttling Explained •  YouTube: Pre-Touch Sensing for Mobile Interaction (Microsoft)
  411. •  YouTube: HTML5DevConf: Jacob Rossi, "Pointer Events, Panning & Zooming,

    and Gestures" •  YouTube: Jacob Rossi, "Pointing Forward" at W3Conf 2013 •  YouTube: Tim Park: Pointing Forward (updated) – JSConf.Asia 2013 •  Flickity – touch, responsive, flickable carousels •  Google Developers / Update: Once Upon an Event Listener •  Google Developers / Update: Improving Scroll Performance with Passive Event Listeners •  Google Developers / Update: Making touch scrolling fast by default
  412. •  Google Developers / Update: Pointing the Way Forward •

     Google Developers / Update: Touch Action Options •  Universal Stylus Initiative (USI) •  Adobe Creative Cloud: Andrew Smyk – Holistic Adaptive Design: Factors to Consider in a Multi-Screen World •  YouTube: Drawboard on Surface Studio with Surface Dial •  AirBar – Touch without a touchscreen •  GitHub: Rafael Pedicini (Rafrex) – Detect It
  413. youtube.com/watch?v=AZKpByV5764

  414. get in touch @patrick_h_lauke github.com/patrickhlauke/touch patrickhlauke.github.io/getting-touchy-presentation slideshare.net/redux paciellogroup.com splintered.co.uk