I have a hybrid mobile app developed with phone gap and targeted for iOS only devices. I use Backbone.js as my MVC framework, jQuery, FastClick.js and Hammer.js for events.
I have a list of items which is vertically scrollable. If I tap on an item, it should open the details view. This works fine if I tap on the item when the list is not scrolling. But if I tap on an item while the list is scrolling or decelerating, it selects the wrong item and shows its details.
I looked at
Tapping on scrolled list generates tap event for wrong element, javascript scroll event for iPhone/iPad? and other sites which suggest that I listen to the onscroll
event of my scrolling list. This event is fired whenever the user scrolls the list. I disable the tap event in the callback for onscroll. I set a timer in the callback with timeout of 300ms and then enable the tap event in that callback which executes after 300 ms. If I get another scroll event before the timer fires, I cancel the earlier timer and set it again to fire after 300ms. There is no other event that gets fired when the scrolling stops completely. So, I have to rely on this event only.
The issue is the event fires even when the scrolling is decelerating and not completely stopped. Due to this, the timer gets fired even while the list is decelerating and not stopped and I run into the wrong details selection issue again. The event fires again when the scroll stops completely as well. If I increase my timer to be >300ms, then in case of non-momentum scroll, it takes longer for the tap to be enabled and the user will keep tapping multiple times.
Below are the code snippets:
When view loads, bind the tap
event and the onscroll
event:
that.$('.scrollListItem').hammer().bind('tap',$.proxy(that.showDetail,that));
this.$('#scrollList').bind('scroll',$.proxy(this.checkscroll,this));
checkscroll
function
checkScroll: function(e){
this.$('.scrollListItem').hammer().unbind('tap');
clearTimeout(myGlobalScrollTimer);
var that = this;
myGlobalScrollTimer = setTimeout(function(){
that.$('.scrollListItem').hammer().bind('tap',$.proxy(that.showDetail,that));
},300);
}
The checkScroll function is firing currently even while the scroll list is decelerating and it hasn't stopped completely. How do I detect that the scrolling is completely stopped and the UI is no longer decelerating and only then enable the tap event? Is there any other way to solution this? Please advice.