i listen for touchstart and touchend events to make my app more responsive for mobile.
the problem is, if you 'flick scroll' (the page is still scrolling even after finger has left screen), and then stop the scroll with a tap - if there is an event on touchend attached to the element you tapped, it will fire.
I need a way to detect if the touchstart or touchend has stopped a scroll, so i can stop any events firing.
I tried setting a variable on scroll (i noticed scroll event on mobile only fires after scroll has finished, i.e page has stopped even on momentum scrolling):
$(window).scroll(function(){
cancelled_scrolling = true;
setTimeout(function(){
cancelled_scrolling = false;
},200);
});
however, when i tap it seems the touchend fires before the .scroll() event, as this doesn't work:
$('body').on('touchend', function(){
if(cancelled_scrolling){
alert('ahahahah');
return false;
}
//code to trigger events depending on event.target after here
});
how can I achieve this?
EDIT:
found an answer to this -
step1 - save the scrollTop on touchend
step2 - on touchstart, check the saved scrollTop against a new scrollTop
if they don't match, the page was scrolled even after the touchend event occurred
On touchStart, keep track of the scrollTop and scrollLeft for each parent node. On touchMove, check if any of these values have changed. If so, cancel the touch. This is slightly better than just checking on touchEnd because maybe they scrolled the page and then unscrolled.
You can also see this logic implemented here: https://github.com/JedWatson/react-tappable/blob/cf755ea0ba4e90dfa6ac970316ff7c35633062bd/src/TappableMixin.js#L120
Related
When i scroll on touchpad with two finger on website it triggers scrolling inertially for 1s-1.5s.
So when i console.log('scroll') it , i see 'scroll' 68 times.
And because of that my programm triggers scroll event multiple times after some delay.
For example i scrolled on touchpad, it got event, and after 1.5s it still triggers scroll.
Question is that, how to make scroll event on touchpad not inertiall, or maybe limit scroll count?
document.addEventListener("wheel", this.wheelFilter, {passive: false});
wheelFilter = e => {
this.updateWheelPrevTime();
this.preventParentScroll();
if (
this._wheelTimeDiff > this._REAL_SCROLL_TIME
) {
this.onMouseWheel(e);
} else {
this.updateWheelFireTime();
}
}
Tried to debounce, doesnt work
Tried to unsubscribe event and then suscribe, it gets prev scroll again
I had implemented zoom in/out an image using mousewheel event which is successfully working. But the behavior is different when I do that with touchpad(using two fingers to zoom in/out). How to differentiate beetween mousewheel event and touchpad events.
The same wheel event unfortunately fires for both pinch and mouse wheel, so it doesn't seem possible at this time to use a different event.
However, I found that the mouse wheel tends to trigger the e.deltaY number in a larger way than pinching.
Thus, I have a listener like so:
const handleZoom = (e) => {
e.preventDefault();
// ignore mouse wheel events that have bigger steps
if (Math.abs(e.deltaY) > 25) {
return;
}
// do what you want to do with pinching here
}
document.addEventListener("wheel", handleZoom);
You can play with the 25 variable to suit your own needs. But for the most part, I noticed that pinch movements are usually much more subtle and have a delta closer to 0, whereas mouse wheel events usually trigger a larger scroll.
First, you have to be careful when designing more advanced touch interactions: when the user uses a mouse it will respond via a click event, but when the user touches the screen both touch and click events will occur. For a single click the order of events is:
1) touchstart
2) touchmove
3) touchend
4) mouseover
5) mousemove
6) mousedown
7) mouseup
8) click
This, of course, means that if you are processing touch events like touchstart, you need to make sure that you don’t process the corresponding mousedown and/or click event as well. If you can cancel the touch events (call preventDefault() inside the event handler), then no mouse events will get generated for touch.
Update:
You can identify touch or click like this:
`
$('#element-id').on('click touchend',function(e){
if(e.type=='click')
console.log('Mouse Click');
else
console.log('Touch');
});
`
Basically I want to disable target from being scrolled to top if the if condition inside handleScroll function is true. So in other words If the condition is true. the user should not be able to scroll to top of the target element anymore and to be able to scroll to bottom of the element.
Also i don't want overflow hidden workarounds if possible.
target.addEventListener('scroll', e => this.handleScroll(e, sectionRect, offset, target));
handleScroll(event, sectionRect, offset, target) {
if ((sectionRect.top - offset) < target.scrollTop)
console.log('dont scroll', event);
},
I dont think its possible you can see more about scroll event here and also i recomend see this part:
"Since scroll events can fire at a high rate, the event handler
shouldn't execute computationally expensive operations such as DOM
modifications. Instead, it is recommended to throttle the event using
requestAnimationFrame, setTimeout or customEvent, as follows:"
and this part:
"In iOS UIWebViews, scroll events are not fired while scrolling is
taking place; they are only fired after the scrolling has completed.
See Bootstrap issue #16202. Safari and WKWebViews are not affected by
this bug."
Maybe creating a custom scroll can be the answer for you.
I have two divs, standing next to each other. In addition to click event I added a swiperight and swipeleft to do something. But when I add these swipe events, scroll doesn't work anymore on iPad. On PCs there's no problem!
Is there any other way to make them compatible with each other on iPad (touch screen devices)?
Merci!
Found a solution:
http://stephband.info/jquery.event.swipe/
Swipe events are a thin wrapper built on top of move events (stephband.info/jquery.event.move). Move events, by default, override native scrolling, as they assume that you want to move something rather than scroll the window. To re-enable scrolling, call e.preventDefault() inside a movestart handler.
In the example above, we want to be able to swipeleft and swiperight, but scroll up and down. Inside a movestart handler, the direction of the finger is moving is calculated and the event is prevented if it is found to be moving up or down::
jQuery('.mydiv')
.on('movestart', function(e) {
// If the movestart is heading off in an upwards or downwards
// direction, prevent it so that the browser scrolls normally.
if ((e.distX > e.distY && e.distX < -e.distY) ||
(e.distX < e.distY && e.distX > -e.distY)) {
e.preventDefault();
}
});
I need to detect mouse movement on the drag of my websites scroll bar, this allows me to detect user inactivity.
When the scroll bar is being dragged the mouse move event is not firing.
Not working in IE11 and Chrome, I'm seeing the mousemove events fire in Firefox 32, I have not tested other browsers.
Sample code:
HTML
<div class="parent" style="background-color:black;width:100px;height:500px;overflow:scroll;">
<div class="child" style="background-color:blue;width:100px;height:1000px"></div>
</div>
Javascript:
var lastMove;
$(window).mousemove(function (e) {
lastMove = new Date();
$(".child").css("background-color", "red");
lastTimeMouseMoved = new Date().getTime();
var t=setTimeout(function(){
var currentTime = new Date().getTime();
if(currentTime - lastTimeMouseMoved > 10){
$(".child").css("background-color", "blue");
}
},10);
});
JS Fiddle:
https://jsfiddle.net/btdxha8k/
Binding to the scroll event is the solution I currently have but I was wondering if there is a more clean solution as I need to bind to 100+ div's that do not need scrolling events as this looks really redundant, dirty and I normally don't like using hacks like this in my code.
Cheers ;)
Mouse move event is triggered only when you move mouse within the screen.
Your issue here scrollbar is not the inner side of screen where mouse move event is captured so you shoul add scroll event with the same function
I'd guess that mouse events aren't raised because the scrollbar is technically outside of your page.
Instead, could you listen for the onscroll event?
https://api.jquery.com/scroll/