iOS/PhoneGap: Prevent scrolling when gesture starts on input element
Posted by Louis Bataillard | Tags: phonegap, javascript, ios, iphone, ipad
When creating an iPhone or iPad application using PhoneGap, I usually try to mimic the behavior of a native application as close as possible. One of the most important thing is to disable the scrolling of the body in the browser window. Even if the current view is not bigger than the screen, the web view allows scrolling. In my opinion, that’s unnecessary and ugly.
Luckily, the scrolling can be disabled using some JavaScript as described here: PhoneGap Wiki: Preventing scrolling on iPhone PhoneGap applications. What this does is it fires a function every time the body is scrolled. This function tells the browser to prevent the default action, which in this case would be scrolling the view. Unfortunately, this doesn’t work when the touching gesture starts on an input or textarea element. When the gesture starts there, the browser never fires the body’s ontouchstart event.
Too complicated? Here are 2 example pages, open them on an iOS device to see what I mean:
Here you can scroll when the gesture starts on the textarea element, and here my solution has been applied so you can’t scroll when the gesture starts on the textarea element
For my current project, an iOS app called “Simple Mail”, the view is exactly the size of the screen, and most of the body is covered with input elements and a texture. Now if the user starts his touch gesture on either of those elements, he will still be able to scroll:

A (partial) solution for this problem I came up with:
- Cover every input with a transparent DIV, the DIV has the exact size of the element it’s covering
- The user doesn’t see that DIV, so when he tries to touch the input element, he actually touches the DIV.
- When the user touches the DIV, I hide it and set the focus on the underlying input element. The user doesn’t notice that anything is different.
- When the input element loses focus, the DIV is once again displayed (although invisible)
However, this is only a partial solution. It works only when the object in question doesn’t already have focus. It doesn’t work when the user first touches the DIV (thus hiding it and focusing the input element) and then starts scrolling. When the input element is already focused and active, there seems to be no way of stopping the user from scrolling the view when starting the gesture on said element.
I put together a class that automates the whole process: First, it looks for every input or textarea element and puts a transparent DIV on top of every one of these elements. Then it binds events to that DIV and the covered elements to handle the showing/hiding of the DIV as well as setting the focus on the input elements
Check out the class here. Just put “covers.addCovers()” in your body’s onload function: <body onload="covers.addCovers()" ontouchmove="event.preventDefault()">