Skip to content

Instantly share code, notes, and snippets.

@mckamey
Created June 13, 2012 23:08
Show Gist options
  • Save mckamey/2927073 to your computer and use it in GitHub Desktop.
Save mckamey/2927073 to your computer and use it in GitHub Desktop.
Polyfill for touch dblclick
/*
Polyfill for touch dblclick
http://mckamey.mit-license.org
*/
function doubleTap(elem, speed, distance) {
if (!('ontouchstart' in elem)) {
// non-touch has native dblclick and no need for polyfill
return;
}
// default dblclick speed to half sec
speed = Math.abs(+speed) || 500;//ms
// default dblclick distance to within 40x40 area
distance = Math.abs(+distance) || 40;//px
var taps, x, y,
reset = function() {
// reset state
taps = 0;
x = NaN;
y = NaN;
};
reset();
elem.addEventListener('touchstart', function(e) {
var touch = e.changedTouches[0] || {},
oldX = x,
oldY = y;
taps++;
x = +touch.pageX || +touch.clientX || +touch.screenX;
y = +touch.pageY || +touch.clientY || +touch.screenY;
// NaN will always be false
if (Math.abs(oldX-x) < distance &&
Math.abs(oldY-y) < distance) {
// fire dblclick event
var e2 = document.createEvent('MouseEvents');
if (e2.initMouseEvent) {
e2.initMouseEvent(
'dblclick',
true, // dblclick bubbles
true, // dblclick cancelable
e.view, // copy view
taps, // click count
touch.screenX, // copy coordinates
touch.screenY,
touch.clientX,
touch.clientY,
e.ctrlKey, // copy key modifiers
e.altKey,
e.shiftKey,
e.metaKey,
e.button, // copy button 0: left, 1: middle, 2: right
touch.target); // copy target
}
elem.dispatchEvent(e2);
}
setTimeout(reset, speed);
}, false);
elem.addEventListener('touchmove', function(e) {
reset();
}, false);
}
function doubleTap(d,h,e){if("ontouchstart"in d){var h=Math.abs(+h)||500,e=Math.abs(+e)||40,i,f,g,j=function(){i=0;g=f=NaN};j();d.addEventListener("touchstart",function(b){var a=b.changedTouches[0]||{},c=f,k=g;i++;f=+a.pageX||+a.clientX||+a.screenX;g=+a.pageY||+a.clientY||+a.screenY;Math.abs(c-f)<e&&Math.abs(k-g)<e&&(c=document.createEvent("MouseEvents"),c.initMouseEvent&&c.initMouseEvent("dblclick",!0,!0,b.view,i,a.screenX,a.screenY,a.clientX,a.clientY,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,b.button,
a.target),d.dispatchEvent(c));setTimeout(j,h)},!1);d.addEventListener("touchmove",function(){j()},!1)}};
<!doctype html><html><head>
<!-- disable default zoom behavior -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<style type="text/css">#foo{background-color:red;height:100px;width:100px;}</style>
</head><body>
<div id="foo"></div>
<script type="text/javascript" src="doubleTap.js"></script>
<script type="text/javascript">
// reference your element
var myElement = document.getElementById('foo');
// enable double tapping (optionally specifying max speed & distance)
doubleTap(myElement);
// use the same as dblclick on desktop
myElement.addEventListener('dblclick', function(e) {
alert('double clicked');
}, false);
</script>
</body>
</html>
@matthijn
Copy link

Where is the like button when you need it :)

@philmander
Copy link

philmander commented Oct 8, 2016

This code is still useful for iOS, but I found that on Chrome 53 for Android, the dblclick event is supported and the polyfill causes dblclicks to run twice. This code:

if (!('ontouchstart' in elem)) {
   // non-touch has native dblclick and no need for polyfill
   return; 
}

...evaluates to false. I'm using this check instead:

if(elem.ondblclick === undefined) {

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