How do I prevent the default behavior of the touchmove event in iOS 5?

natlee75 picture natlee75 · Oct 13, 2011 · Viewed 17.2k times · Source

I have a web-based application that includes a component that the user can scroll up and down with their finger. I use the event's preventDefault method to prevent the default behavior where the touch move shifts the whole screen around on iOS devices.

Unfortunately this does not seem to work anymore in iOS 5 which I just upgraded to this morning. I have to assume that this is just done differently in iOS 5, but I have yet to be able to find a resource that provides instructions.

Update #1: I haven't been able to find an answer to my specific question, but I was able adjust my code a bit to use the -webkit-overflow-scrolling style (set to a value of "touch") and implement the snazzy inertial scrolling capability (where the content scrolls faster depending on the velocity of your swipe and will "rubber band bounce" back if it hits the boundaries. Pretty cool looking...

Update #2: I have another strange problem now. For some odd reason that overflow scrolling behavior gets mixed up sometimes whereby you have to drag your finger left and right across the containing element in order to make its contents move up and down. I have yet to be able to figure out why this happens - does anyone have any ideas?

Answer

Andreas Köberle picture Andreas Köberle · Jun 15, 2012

I found a very simple solution. When the event hits your element that is allowed to scroll, just flag the event. On the event listener on the document just check if the flag is set and only stop the event if the flag isn't set:

this.$scrollableEl.on('touchmove', function(event){
  event.comesFromScrollable = true;
  // when you have containers that are srollable but 
  // doesn't have enough content to scroll sometimes:
  // event.comesFromScrollable = el.offsetHeight < el.scrollHeight;
});

$(document).on('touchmove', function(event){
    if (!event.comesFromScrollable){
      event.preventDefault();
    }
});

You could also use event.stopImmediatePropagation instead, so you dont need the eventListener on the document element, but this breaks zepto.js tap in my case:

this.$scrollableEl.on('touchmove', function(event){
  event.stopImmediatePropagation();
});