Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PreventGhostClick
/**
* Prevent click events after a touchend.
*
* Inspired/copy-paste from this article of Google by Ryan Fioravanti
* https://developers.google.com/mobile/articles/fast_buttons#ghost
*
* USAGE:
* Prevent the click event for an certain element
* ````
* PreventGhostClick(myElement);
* ````
*
* Prevent clicks on the whole document (not recommended!!) *
* ````
* PreventGhostClick(document);
* ````
*
*/
(function(window, document, exportName) {
var coordinates = [];
var threshold = 25;
var timeout = 2500;
// no touch support
if(!("ontouchstart" in window)) {
window[exportName] = function(){};
return;
}
/**
* prevent clicks if they're in a registered XY region
* @param {MouseEvent} ev
*/
function preventGhostClick(ev) {
for (var i = 0; i < coordinates.length; i++) {
var x = coordinates[i][0];
var y = coordinates[i][1];
// within the range, so prevent the click
if (Math.abs(ev.clientX - x) < threshold && Math.abs(ev.clientY - y) < threshold) {
ev.stopPropagation();
ev.preventDefault();
break;
}
}
}
/**
* reset the coordinates array
*/
function resetCoordinates() {
coordinates = [];
}
/**
* remove the first coordinates set from the array
*/
function popCoordinates() {
coordinates.splice(0, 1);
}
/**
* if it is an final touchend, we want to register it's place
* @param {TouchEvent} ev
*/
function registerCoordinates(ev) {
// touchend is triggered on every releasing finger
// changed touches always contain the removed touches on a touchend
// the touches object might contain these also at some browsers (firefox os)
// so touches - changedTouches will be 0 or lower, like -1, on the final touchend
if(ev.touches.length - ev.changedTouches.length <= 0) {
var touch = ev.changedTouches[0];
coordinates.push([touch.clientX, touch.clientY]);
setTimeout(popCoordinates, timeout);
}
}
/**
* prevent click events for the given element
* @param {EventTarget} el
*/
window[exportName] = function(el) {
el.addEventListener("touchstart", resetCoordinates, true);
el.addEventListener("touchend", registerCoordinates, true);
};
document.addEventListener("click", preventGhostClick, true);
})(window, document, 'PreventGhostClick');
@kosich

This comment has been minimized.

Copy link

kosich commented Apr 2, 2015

please, check this one
its based not on blocking some square on the screen, but rather blocking events from other device (after touch interaction mouse events are blocked for some period and vice versa)
note: its a draft for angular-hammer use, so one would need to modify it a little to use with native elements ( atm it accepts jQuery element and addresses dom via element[0] )

@singleclown

This comment has been minimized.

Copy link

singleclown commented Nov 13, 2017

It's great, but I don't know how to restore it. How about restoring it with removeEventListener?

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 17, 2019

using PreventGhostClick(document) disables all anchor <a href="valid-link-here">, is there a solution to make it work?

@ghost

This comment has been minimized.

Copy link

ghost commented Jul 4, 2019

What about using this instead (for tap/click)?
https://github.com/ftlabs/fastclick/blob/master/lib/fastclick.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.