Reputation: 25810
I have two elements, a parent node and child. The child is scrollable only vertically (overflow: hidden; overflow-y: scroll;
). The parent can be scrolled only horizontally (overflow: hidden; overflow-x: scroll;
). When I swipe sideways over the child node, no scroll event is ever fired despite doing this:
//NEITHER of these are fired when swiping sideways on the child
child.addEventListener( "scroll", listener, true );
parent.addEventListener( "scroll", listener2, true );
The browser only fires a scroll event if I scroll vertically while over the child! Neither listener
nor listener2
is ever called! How do I get it to fire a horizontal scroll for a parent element if the child element has only one direction scrolling?
Fiddle Mobile Example: https://jsfiddle.net/cn2hfLok/2/embedded/result/
HTML:
<div class="parent">
<div class="child">
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
content<br />content<br />content<br />content<br />content<br />content<br />content<br />
</div>
<div style="width: 5000px;">s</div>
</div>
CSS:
.parent
{
position:relative;
width: 600px;
height: 100%;
background-color: yellow;
overflow: hidden;
overflow-x: scroll;
}
.child
{
position:relative;
width: 50%;
height: 200px;
background-color: blue;
overflow: hidden;
overflow-y: scroll;
}
JavaScript:
function scrollC(e)
{
console.log( "child" );
}
function scrollP(e)
{
console.log( "parent" );
}
document.querySelector( ".child" ).addEventListener( "scroll", scrollC );
document.querySelector( ".parent" ).addEventListener( "scroll", scrollP );
EDIT: It appears even with overflow: scroll
on the child, if there's nothing to scroll horizontally, it still won't fire a scroll event! https://jsfiddle.net/cn2hfLok/4/embedded/result/
Upvotes: 2
Views: 3249
Reputation: 25810
It is impossible to capture a scroll event on iOS Safari for the parent if the child has nothing to scroll in the direction you're attempting to move or it doesn't listen to that direction. To overcome this, you need to listen to touch events on the child and then pass that movement on to the parent by changing the parent's scrollLeft
or scrollTop
which will fire the parent's scroll event handler.
Listen to:
touchstart
capture the starting position
touchmove
check the current position against the start, if it moves horizontally (and little enough vertically), then pass to the parent by parent.scrollLeft += startX - e.clientX;
and then call e.stopPropagation();e.preventDefault();
so it doesn't move the page. (Also update your startX
to be the e.clientX
)
touchend
and touchleave
Set some variable to tell your touchmove
handler to stop listening, for example notDragging = true;
Upvotes: 3
Reputation: 1751
I think you should move in the following direction:
Enable the capturing phase for a handler: document.querySelector( ".parent" ).addEventListener( "scroll", scrollP, true );
Stop propagation in the parent callback: e.stopPropagation();
In this case the parent's listener will intercept all events including horizontal scroll
. But actually you can filter them by event.type
and a bunch of other accessible properties.
Here's the updated example: https://jsfiddle.net/cn2hfLok/7/
Upvotes: 0