skip to Main Content

This question is an update to this one, but for modern browsers. (Unfortunately the answers here are outdated and/or not in vanilla JavaScript). Essentially I want to perform a simple test to detect if a click event was triggered by touch or mouse input.

The only answer in the aforementioned question that is foolproof and still works is to use the event.pointerType property. However, event.pointerType seems to only be defined in Chrome for the click event.

While I could use pointer-events (for instance pointerup), for which event.pointerType is defined for all browsers, pointerup behaves differently than click and is more similar to mouseup. In other words it does not register only true clicks, but also fires if the pointer was dragged around or started on another element.

For this reason, I would like to get this to work with regular click events. If anyone knows how I can reliably detect the input method it would be greatly appreciated.

2

Answers


  1. A solution could be, first have a flag to check if get touched or not let’s call it isTouched, this flag is false by default, and create an event listener on the touchstart event and once it get triggered it will turn isTouched to be true, also create another event listener for click and inside it conditionally check if isTouched is true, then reset the isTouched to be false, if it is with false, then there wasn’t a touch event triggered, so it is just a click event.

    let isTouched = false;
    const testButton = document.getElementById('test');
    
    testButton.addEventListener('touchstart', function(e) {
      isTouched = true;
    });
    
    
    testButton.addEventListener('click', function(e) {
      if (isTouched) {
        alert('Triggered by touch');
        isTouched = false;
      } else {
        alert('Triggered by mouse click');
      }
    });
    <button id="test">Test</button>
    Login or Signup to reply.
  2. A similar approach to the accepted answer but hiding the implementation by dispatching a PointerEvent for those browsers that do not support yet click event as PointerEvent

    We can create a wrapper function that adds the click listener
    and handles the logic for touch devices

    function addPointerClickEvent(target, listener, options) {
    
      let isTouch = false
    
      const listenerWrapper = event => {
        if (!(event instanceof PointerEvent)) {
          const pointerType = isTouch ? 'touch' : 'mouse'
    
          const eventOptions = {...event, pointerType}
    
          const pointerEvent = new PointerEvent('click', eventOptions)
    
          target.dispatchEvent(pointerEvent)
    
          isTouch = false
    
          return
        }
    
        listener.call(target, event)
      }
    
      target.addEventListener(
        'touchstart',
        event => isTouch = true,
        {capture: true},
      )
    
      target.addEventListener('click', listenerWrapper, options)
    
    }
    

    And once we have the function we use it like this

    const target = document.querySelector('.target')
    
    addPointerClickEvent(target, event => {
      console.log(event.type, event.pointerType, event)
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search