Easily bind `click` event handlers to `tap` events
Browser click
events on touch-oriented devices carry with them a sluggish 300ms delay. This extension to jQuery (or Zepto) intercepts click
event handlers and turns them into tap
event handlers so you can respond to user input faster.
But wait! After your tap
handler fires, a click
event will be fired at the same x, y coordinates 300ms later. This extension will block the resulting click event if the tap handler has fired.
/*global define: false, window: false */
define(['jquery'], function ($) {
'use strict';
return function () {
/* Begin monkey-patch Tap event support into $ */
var x = 0,
y = 0,
threshold = 40,
// Sometimes there is lag between the last update and touchend.
// Unfortunately, we can't get coords on touchend, so this is
// the fudge factor.
indexOfTap = function(x, y) {
var i, len, tapX, tapY;
for(i = 0, len = taps.length; i < len; i++) {
tapX = taps[i][0];
tapY = taps[i][1];
if (Math.abs(tapX - x) <= threshold &&
Math.abs(tapY - y) <= threshold) {
return i;
}
}
return -1;
},
makeTap = function (callback) {
return function (e) {
return callback.call(this, e);
};
},
wrapClick = function (callback) {
return function (e) {
var tap = indexOfTap(e.x, e.y);
if (tap !== -1) {
taps.splice(tap, 1); // remove the tap
e.preventDefault();
e.stopPropagation();
return;
}
return callback.call(this, e);
};
};
var taps = [];
try {
var update = function (e) {
x = e.touches[0].clientX;
y = e.touches[0].clientY;
};
window.addEventListener('touchstart', update, true);
window.addEventListener('touchmove', update, true);
window.addEventListener('touchend', function (e) {
taps.push([x,y]);
}, true);
} catch (o_O){
//could not register listeners
}
$.fn.oldBind = $.fn.bind;
$.fn.oldDelegate = $.fn.delegate;
$.fn.bind = function (event, callback) {
if (event.indexOf('click') > -1) {
this.oldBind('tap', makeTap(callback));
this.oldBind(event, wrapClick(callback));
} else {
this.oldBind(event, callback);
}
return this;
};
$.fn.delegate = function (selector, event, callback) {
if (event.indexOf('click') > -1) {
this.oldDelegate(selector, 'tap', makeTap(callback));
this.oldDelegate(selector, event, wrapClick(callback));
} else {
this.oldDelegate(selector, event, callback);
}
return this;
};
/* end monkey-patch Tap event support into $ */
};
});
See the gist at https://gist.github.com/3702931
Written by Jason Denizac
Related protips
3 Responses
Otherwise use this https://gist.github.com/4375465
over 1 year ago
·
@mlb I would be interested in seeing these 2 methods benchmarked against each other
over 1 year ago
·
Awesome, thanks for this. Had problems with the tap event in jquery mobile that this could solve.
over 1 year ago
·
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Jquery
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#