Skip to content

Instantly share code, notes, and snippets.

@ethanny2
Created May 27, 2020 00:46
Show Gist options
  • Save ethanny2/44d5ad69970596e96e0b48139b89154b to your computer and use it in GitHub Desktop.
Save ethanny2/44d5ad69970596e96e0b48139b89154b to your computer and use it in GitHub Desktop.
Vanilla JavaScript Double tap event detection on mobile using setTimeout
/* Based on this http://jsfiddle.net/brettwp/J4djY/*/
function detectDoubleTapClosure() {
let lastTap = 0;
let timeout;
return function detectDoubleTap(event) {
const curTime = new Date().getTime();
const tapLen = curTime - lastTap;
if (tapLen < 500 && tapLen > 0) {
console.log('Double tapped!');
event.preventDefault();
} else {
timeout = setTimeout(() => {
clearTimeout(timeout);
}, 500);
}
lastTap = curTime;
};
}
/* Regex test to determine if user is on mobile */
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
document.body.addEventListener('touchend', detectDoubleTapClosure());
}
@emekaorji
Copy link

Smooth!

@jonobr1
Copy link

jonobr1 commented Mar 29, 2023

Configuring your event listener as not passive will improve the performance of this. E.g:

document.body.addEventListener('touchend', detectDoubleTapClosure(), { passive: false });

More info here: https://dom.spec.whatwg.org/#dom-eventlisteneroptions-passive

@jasonm23
Copy link

Just putting that together with the code for easy copy. No changes.

/* Based on this http://jsfiddle.net/brettwp/J4djY/*/
function detectDoubleTapClosure() {
  let lastTap = 0;
  let timeout;
  return function detectDoubleTap(event) {
    const curTime = new Date().getTime();
    const tapLen = curTime - lastTap;
    if (tapLen < 500 && tapLen > 0) {
      console.log('Double tapped!');
      event.preventDefault();
    } else {
      timeout = setTimeout(() => {
        clearTimeout(timeout);
      }, 500);
    }
    lastTap = curTime;
  };
}

/* Regex test to determine if user is on mobile */
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
    document.body.addEventListener('touchend', detectDoubleTapClosure(), { passive: false });
}

@twilson90
Copy link

The end of a pinch gesture will also trigger this, unless you carefully lift both fingers simultaneously.

@Neophen
Copy link

Neophen commented Nov 8, 2023

why are you using the timeout? it doesn't do anything?

@KevynTD
Copy link

KevynTD commented Jun 26, 2024

very good, I modified it a little with 3 additions:

  • You can now listen for the doubletap event on any element on the page after it is initialized
  • work on desktop and mobile
  • customize time to detect doubletap
/* Based on ethanny2 solution: https://gist.github.com/ethanny2/44d5ad69970596e96e0b48139b89154b */
function detectDoubleTap(doubleTapMs) {
  let timeout, lastTap = 0
  return function detectDoubleTap(event) {
    const currentTime = new Date().getTime()
    const tapLength = currentTime - lastTap
    if (0 < tapLength && tapLength < doubleTapMs) {
      event.preventDefault()
      const doubleTap = new CustomEvent("doubletap", {
        bubbles: true,
        detail: event
      })
      event.target.dispatchEvent(doubleTap)
    } else {
      timeout = setTimeout(() => clearTimeout(timeout), doubleTapMs)
    }
    lastTap = currentTime
  }
}

// initialize the new event
document.addEventListener('pointerup', detectDoubleTap(500));

// put the addEventListener on some tag
document.querySelector('button').addEventListener('doubletap', (event) => {
  event.target.insertAdjacentHTML("afterend", "<br>doubleTaped")
})

Working here: https://jsfiddle.net/Byte/adLxjmtw/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment