Prevent touchmove default on parent but not child
Solution 1
Try this:
$('#fix').on('touchmove',function(e){
if(!$('.scroll').has($(e.target)).length)
e.preventDefault();
});
EDITED
e.target contains the final target node of the touch event. You can stop all events that are not "bubbling accross" your .scroll divs.
I think there are better solutions, but this one must be ok.
Solution 2
document.addEventListener('touchmove', function(e){e.preventDefault()}, false);
document.getElementById('inner-scroll').addEventListener('touchmove', function(e){e.stopPropagation()}, false);
The idea is that your main scroll is always (to your discretion) disabled, but in your inner-scroll you prevent the event from bubbling up (or propagating), so it will never reach the first event listener, which would ultimately cancel the touchmove event.
I hope this is what you were looking for. I've had a situation similar to yours, where the main scroll was disabled on tablet, but i wanted an inner scroll to work. This seemed to do the job.
Solution 3
This should work:
$(document).on('touchmove', function(e) {
if (!$(e.target).parents('.scroll')[0]) {
e.preventDefault();
}
});
Solution 4
I found an interesting discussion here: https://github.com/joelambert/ScrollFix/issues/2 , and there's a good solution from bjrn
Basically, it takes advantage of flex boxes. Worked well for me on ipad. Here is a test link he set up that shows it at work: http://rixman.net/demo/scroll/
What's especially nice about this solution is that it's all CSS and no javascript required.
Solution 5
I found another solution using css-classes and document.ontouchmove. I'm developing an IPad Webapp with Sliders and wanted to prevent all the other elements to bounce when there's a touchmove event. This is my solution as an abstract:
HTML:
<body>
<div id="outterFrame" class="fullscreen"> <!-- class fullscreen is self-explaining I guess -->
<div id="touchmove_enabled class="enable_touchmove sliderbutton">Button</div>
</div>
</body>
Javascript:
/* preventDefault on touchmove events per default */
document.ontouchmove = function(event)
{
var sourceElement = event.target || event.srcElement;
if(!hasClass(sourceElement,"enable_touchmove"))
{
e.preventDefault();
}
};
/* helper method "hasClass" */
function hasClass(element,class)
{
if(element.className != null)
{
return element.className.match(new RegExp('(\\s|^)'+class+'(\\s|$)'));
}
return false;
}
Now, only the touchmove event of the div "touchmove_enabled" is fired.
Probably my solution may be useful for somebody. Patric
![will](https://i.stack.imgur.com/WYlng.jpg?s=256&g=1)
Comments
-
will almost 2 years
I am creating a little web app for the iPad and I've got several elements I am preventing the user from scrolling by preventing default on the touchmove event. However, I have a situation where I need the user to be able to scroll a child element.
I have tried to use e.stopPropagation(); but no luck! I also attempted to detect the element under the finger and put the e.preventDefault(); inside an if statement, but again, no luck. Or maybe I was just getting mixed up...
Any ideas? Removing the .scroll divs from the #fix div is a last resort really as it will cause all sorts of headaches.
EDIT
I managed to sort it. Seems like I didn't understand the use of .stopPropagation(); oops!
The working code:
<div id="fix"> <h1>Hi there</h1> <div class="scroll"> <ul> <li>List item</li> <li>List item</li> <li>List item</li> </ul> </div> <div class="scroll"> <ul> <li>List item</li> <li>List item</li> <li>List item</li> </ul> </div> </div>
And the Javascript:
$('body').delegate('#fix','touchmove',function(e){ e.preventDefault(); }).delegate('.scroll','touchmove',function(e){ e.stopPropagation(); });