Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable scrolling in an iPhone web application?

Is there any way to completely disable web page scrolling in an iPhone web app? I've tried numerous things posted on google, but none seem to work.

Here's my current header setup:

<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/> <meta name="apple-mobile-web-app-capable" content="yes"/> 

document.body.addEventListener('touchmove', function(e){ e.preventDefault(); });

doesn't seem to work.

like image 654
Stefan Kendall Avatar asked May 23 '10 01:05

Stefan Kendall


People also ask

How do you turn off scroll on iPhone?

Go to Settings and tap Accessibility. Turn on the feature, then use the slider to select a sensitivity level.

How do I disable scrolling on my website?

To hide the horizontal scrollbar and prevent horizontal scrolling, use overflow-x: hidden: HTML. CSS.

How do I disable scrolling in the background when the phone menu is open?

When the mobile menu is active (overlay) want to prevent that the body is scroll able, disable scroll for body.


2 Answers

document.addEventListener('touchstart', function (e) {     e.preventDefault(); }); 

Do not use the ontouchmove property to register the event handler as you are running at risk of overwriting an existing event handler(s). Use addEventListener instead (see the note about IE on the MDN page).

Beware that preventing default for the touchstart event on the window or document will disable scrolling of the descending areas.

To prevent the scrolling of the document but leave all the other events intact prevent default for the first touchmove event following touchstart:

var firstMove;  window.addEventListener('touchstart', function (e) {     firstMove = true; });  window.addEventListener('touchmove', function (e) {     if (firstMove) {         e.preventDefault();          firstMove = false;     } }); 

The reason this works is that mobile Safari is using the first move to determine if body of the document is being scrolled. I have realised this while devising a more sophisticated solution.

In case this would ever stop working, the more sophisticated solution is to inspect the touchTarget element and its parents and make a map of directions that can be scrolled to. Then use the first touchmove event to detect the scroll direction and see if it is going to scroll the document or the target element (or either of the target element parents):

var touchTarget,     touchScreenX,     touchScreenY,     conditionParentUntilTrue,     disableScroll,     scrollMap;  conditionParentUntilTrue = function (element, condition) {     var outcome;      if (element === document.body) {         return false;     }      outcome = condition(element);      if (outcome) {         return true;     } else {         return conditionParentUntilTrue(element.parentNode, condition);     } };  window.addEventListener('touchstart', function (e) {     touchTarget = e.targetTouches[0].target;     // a boolean map indicating if the element (or either of element parents, excluding the document.body) can be scrolled to the X direction.     scrollMap = {}      scrollMap.left = conditionParentUntilTrue(touchTarget, function (element) {         return element.scrollLeft > 0;     });      scrollMap.top = conditionParentUntilTrue(touchTarget, function (element) {         return element.scrollTop > 0;     });      scrollMap.right = conditionParentUntilTrue(touchTarget, function (element) {         return element.scrollWidth > element.clientWidth &&                element.scrollWidth - element.clientWidth > element.scrollLeft;     });      scrollMap.bottom =conditionParentUntilTrue(touchTarget, function (element) {         return element.scrollHeight > element.clientHeight &&                element.scrollHeight - element.clientHeight > element.scrollTop;     });      touchScreenX = e.targetTouches[0].screenX;     touchScreenY = e.targetTouches[0].screenY;     disableScroll = false; });  window.addEventListener('touchmove', function (e) {     var moveScreenX,         moveScreenY;      if (disableScroll) {         e.preventDefault();          return;     }      moveScreenX = e.targetTouches[0].screenX;     moveScreenY = e.targetTouches[0].screenY;      if (         moveScreenX > touchScreenX && scrollMap.left ||         moveScreenY < touchScreenY && scrollMap.bottom ||         moveScreenX < touchScreenX && scrollMap.right ||         moveScreenY > touchScreenY && scrollMap.top     ) {         // You are scrolling either the element or its parent.         // This will not affect document.body scroll.     } else {         // This will affect document.body scroll.          e.preventDefault();          disableScroll = true;     } }); 

The reason this works is that mobile Safari is using the first touch move to determine if the document body is being scrolled or the element (or either of the target element parents) and sticks to this decision.

like image 31
Gajus Avatar answered Oct 09 '22 22:10

Gajus


Change to the touchstart event instead of touchmove. Under One Finger Events it says that no events are sent during a pan, so touchmove may be too late.

I added the listener to document, not body.

Example:

document.ontouchstart = function(e){      e.preventDefault();  } 
like image 89
drawnonward Avatar answered Oct 09 '22 23:10

drawnonward