I have a scrollable list on a mobile device. They want people to be able to scroll the list via swiping, and also select a row by tapping.
The catch is combining th
jQuery Mobile has a .tap() event which seems to have the behavior you'd expect:
The jQuery Mobile tap event triggers after a quick, complete touch event that occurs on a single target object. It is the gesture equivalent of a standard click event that is triggered on the release state of the touch gesture.
This might not necessarily answer the question, but might be a useful alternative to some.
I did this with a bit of a different work around. It's definitely not very elegant and certainly not suited to most situations, but it worked for me.
I have been using jQuery's toggleSlide() to open and close input divs, firing the slide on touchstart. The problem was that when the user wanted to scroll, the touched div would open up. To stop this from happening, (or to reverse it before the user noticed) I added a touchslide event to the document which would close the last touched div.
In more depth, here is a code snippet:
var lastTouched;
document.addEventListener('touchmove',function(){
lastTouched.hide();
});
$('#button').addEventListener('touchstart',function(){
$('#slide').slideToggle();
lastTouched = $('#slide');
});
The global variable stores the last touched div, and if the user swipes, the document.touchmove event hides that div. Sometimes you get a flicker of a div poking out but it works for what I need it to, and is simple enough for me to come up with.
Some of these solutions worked for me, but in the end I found that this lightweight library was simpler to setup.
Tocca.js: https://github.com/GianlucaGuarini/Tocca.js
It's quite flexible and detects touch as well as swipe, double-tap etc.
I came across this elegant solution that works like a charm using jQuery. My problem was preventing list items from calling their touch start event during scrolling. This should also work for swiping.
bind touchstart to each item that will be scrolled or swiped using a class 'listObject'
$('.listObject').live('touchstart', touchScroll);
Then to each item assign a data-object attr defining the function to be called
<button class='listObject' data-object=alert('You are alerted !')>Alert Me</button>
The following function will effectively differentiate between a tap and scrolling or swiping.
function touchScroll(e){
var objTarget = $(event.target);
if(objTarget.attr('data-object')){
var fn = objTarget.attr('data-object'); //function to call if tapped
}
if(!touchEnabled){// default if not touch device
eval(fn);
console.log("clicked", 1);
return;
}
$(e.target).on('touchend', function(e){
eval(fn); //trigger the function
console.log("touchEnd")
$(e.target).off('touchend');
});
$(e.target).on('touchmove', function(e){
$(e.target).off('touchend');
console.log("moved")
});
}
I had the same problem, here's a quick solution which works for me
$(document).on('touchstart', 'button', function(evt){
var oldScrollTop = $(window).scrollTop();
window.setTimeout( function() {
var newScrollTop = $(window).scrollTop();
if (Math.abs(oldScrollTop-newScrollTop)<3) $button.addClass('touchactive');
}, 200);
});
basically instead of handling touchstart immediately, wait for some milliseconds (200ms in this example), then check the scroll position, had scrollposition changed, then we need not to handle touchstart.
I use this bit of code so that buttons are only triggered (on touchend) if not being swiped on:
var startY;
var yDistance;
function touchHandler(event) {
touch = event.changedTouches[0];
event.preventDefault();
}
$('.button').on("touchstart", touchHandler, true);
$('.button').on("touchmove", touchHandler, true);
$('.button').on("touchstart", function(){
startY = touch.clientY;
});
$('.button').on('touchend', function(){
yDistance = startY - touch.clientY;
if(Math.abs(yDist) < 30){
//button response here, only if user is not swiping
console.log("button pressed")
}
});