A very important part of implementing web applications for mobile devices is, of course, to handle touch events in way that feels natural to the user.
I recently fixed a bug in one of my projects where a swipe up/down to scroll was interpreted as a tap on the item where the user touched the screen to swipe scroll. The bug appeared since the application was listening for the touchend
event to trigger the 'click' logic. The problem with this is that the touchend
event is fired no matter if the user tapped a single spot on the screen or swiped.
To distinguish between a tap and a swipe I decided to track if the user did any movement while during the touch gesture, and if so the click logic was not triggered. Since this is a piece of code I will need in more than one of my projects I made it into a jQuery plugin.
Below is the implementation of the jQuery plugin I wrote, which adds an onTap
function which takes a callback. The callback will be called when the user taps the element(s) without swiping.
(function ($) {
$.fn.onTap = function (callback) {
function currentScrollPosition () {
return $(window).scrollTop();
}
var touchStartPosition = 0;
var maxTouchMovement = 0;
this.on('touchstart', function () {
maxTouchMovement = 0;
touchStartPosition = currentScrollPosition();
return true;
});
this.on('touchend', function () {
if (maxTouchMovement < 5) {
callback.call(this);
return false;
}
return true;
});
this.on('touchmove', function () {
var currentDistanceFromTouchStart = Math.abs(touchStartPosition - currentScrollPosition());
maxTouchMovement = Math.max(maxTouchMovement, currentDistanceFromTouchStart);
return true;
});
return this;
}
})(jQuery)
The jQuery plugin can now be used by passing in a function which, in the usual jQuery style, can access the element(s) in question through 'this':
$(function () {
$('.some_selector_here').onTap(function () {
// Do something smart with the tapped element
$(this).toggleClass('tapped');
})
})
By using the touchmove
event to find the maximum distance from the starting point the user moved to during the touch gesture we can make sure that even if the user returns to the starting position the gesture is not seen as a tap. Only a touch and release in the same spot without any major movement during the touch is seen as a tap gesture.
Comments