Search code examples
javascriptgoogle-chromeaddeventlistenertouchscreentouchstart

Differentiate touchstart + touchend vs. click


With vanilla JS, and no touch framework, what condition makes a touchstart + touchend become a click event?

Is there an official specification like, for example:

touchstart followed by touchend, with delta_time < 100 ms    => triggers a "click" event

?

If so, is the standard followed by Chrome and Firefox?

Example: if you do a touchstart, then you keep the finger pressed for 2 seconds and then release the finger (touchend), it won't trigger a click.

document.querySelector("div").addEventListener("touchstart", evt => { console.log("touchstart"); }, {passive: true});
document.querySelector("div").addEventListener("touchend", evt => { console.log("touchend"); }, {passive: true});
document.querySelector("div").addEventListener("click", evt => { console.log("click"); }, {passive: true});
<div>Hello<br>Hello<br>Hello</div>


Solution

  • There is no real delta time that you can know about, as this might change from input device to input device and from system to system. In accessibility some people with slower motor skills might have to turn up that delta so their interaction counts as a click. You can see this mentioned in the MDN docs in the Usage Notes and the specification refers to (a term I have never encoutered before but you learn something every day): hysteresis.

    In the spec it says that as long as they fall within the same hysteresis it should be considered a click, but the interval between the two events is determined by the system and as far as I know, not revealed through the browser. I presume this is to prevent fingerprinting browsers, although I do think it would be useful if you want to be able to simulate click events yourself (which the specification actually discourages in my quick reading).

    Since most people don't switch pointer devices on the fly, perhaps the best way to see what pointer event was likely used is to just match it with CSS: window.matchMedia('(pointer:coarse)').matches should tell you whether it was a touch or a mouse event?

    document.addEventListener( 'click', event => {
      
      event.preventDefault();
      
      if( window.matchMedia( 'pointer:coarse' ).matches ){
          
        console.log( 'Probably a touch event click' );
        
      } else {
      
        console.log( 'Probably a mouse event click' );
        
      }
      
    })