/** * 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');