I am implementing a website and want to stop users go to the previous page when they scroll with two fingers on their touchpad. I tried to add scroll event and stop propagation but it doesn't work.
document.addEventListener('scroll', (e) => {e.stopPropagation()});
document.addEventListener('touchstart', (e) => {e.stopPropagation()});
document.addEventListener('touchend', (e) => {e.stopPropagation()});
Is there any way to solve this issue?
I have tried to disable touch-action in css but it still doesn't work:
touch-action: none;
I use below code to solve the issue:
export const disableScroll = () => {
windowOnweel = window.onwheel;
window.onwheel = e => {
e = e || window.event;
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
};
};
but you need to remember to restore the onwheel method when you don't need that.
Related
We have a mobile app exhibiting very odd behavior. On desktops it works fine. But on mobile devices, touch events are not being handled properly.
This is the event setup code:
document.addEventListener('mousemove', e =>
{
this.mouseMoveListener(e);
});
document.addEventListener('mousedown', e =>
{
this.mouseDownListener(e);
});
document.addEventListener('mouseup', e =>
{
this.mouseUpListener(e);
});
document.addEventListener('touchmove', e => firstTouchEventCancel(this.mouseMoveListener(e)), true);
document.addEventListener('touchstart', e => firstTouchEventCancel(this.mouseDownListener(e)), true);
document.addEventListener('touchend', e => firstTouchEventCancel(this.mouseUpListener(e)), true);
the function firstTouchEventCancel is as follows:
export function firstTouchEventCancel(fn, thisObj)
{
if (thisObj)
{
fn = fn.bind(thisObj)
}
return function (e)
{
e.preventDefault()
e.stopPropagation()
return fn(e.changedTouches[0])
}
}
I've logged the e / event variable immediately in both the firstTouchEventCancel method and in the event handler methods. In both cases the event is an empty object.
I need the event to tell me where the user touched and swiped if they are swiping. But I'm getting nothing. There are no other event handlers setup that might be consuming the event. Plus if there were these methods would not be called.
Has anyone run into this?
In all of the event handlers on mobile the events sent to the listeners are empty.
My question is similiar to this How to prevent page scrolling when scrolling a DIV element? but I'm wondering if there is an approach with css and/or react that does not require jQuery.
I want to disable page scrolling on a mouseWheel event when the cursor is over one particular div.
The div is a graph which zooms on a mouseWheel event, and is rendered by a React component.
I've tried e.preventDefault however chrome tells me
Unable to preventDefault inside passive event listener due to target being treated as passive
Can anyone help? Thanks in advance.
EDIT: Found a simple solution for anyone looking.
changeScroll(){
let style = document.body.style.overflow
document.body.style.overflow = (style === 'hidden') ? 'auto':'hidden'
}
<div
onMouseEnter={this.changeScroll}
onMouseLeave={this.changeScroll} />
<ReactComponent/>
</div>
Thanks! I was looking for a current answer for managing it.
My ReactJS solution was to add and remove the event when onMouseEnter/Leave is detected. Additionally, with the use of passive, taken from this answer link.
Principal component:
<Wrapper
onWheel={this.handleScroll}
onMouseEnter={this.disableScroll}
onMouseLeave={this.enableScroll}
> ...</Wrapper>
handleScroll():
public handleScroll = (event) => {
if (event.deltaY > 0) {
this.decreaseValue()
} else {
this.increaseValue()
}
}
enableScroll():
public enableScroll = () => {
document.removeEventListener('wheel', this.preventDefault, false)
}
disableScroll():
public disableScroll = () => {
document.addEventListener('wheel', this.preventDefault, {
passive: false,
})
}
preventdefault():
public preventDefault(e: any) {
e = e || window.event
if (e.preventDefault) {
e.preventDefault()
}
e.returnValue = false
}
I have circle menu with rotation. And after simple click i want to fire click event, but during rotation - mousemove i want ignore click. For now i have -
<g id="bottomMenuRotate" onMouseDown={this.selectElement.bind(this)}>
Then my select function looks -
selectElement(e){
let groupRotate = document.getElementById('bottomMenuRotate');
groupRotate.onmousemove = function(e) {....}
groupRotate.onmouseup = function(e){
groupRotate.onmousemove = null;
}
}
So how i cant prevent click? I tried something like
groupRotate.onmouseup = function(e){
e.stopPropagation();
groupRotate.onmousemove = null;
};
or
groupRotate.onmouseclick = function(e){
e.stopPropagation();
}
but this prevents every click. Any tips how i can do it?
So i finally found simply solution
selectElement(e){
let move = false;
groupRotate.onmousemove = function(e) {
move = true;
}
groupRotate.onclick = function(e){
move ? e.preventDefault() : false;
}
}
This prevent click only when move is set to true.
Set a state in your onMouseMove handler that prevents the click events from running:
groupRotate.onmousemove = (e) => {
this.setState({ mouseMoving: true });
}
groupRotate.onmouseup = (e) => {
this.setState({ mouseMoving: false });
}
Somewhere else:
groupRotate.onmouseclick = (e) => {
if (!this.state.mouseMoving) {
...
};
}
Note the arrow functions to make this available within the functions.
I'm messing around with touch events on a touch slider and I keep getting the following error:
Ignored attempt to cancel a touchmove event with cancelable=false,
for example because scrolling is in progress and cannot be
interrupted.
I'm not sure what is causing this problem, I am new to working with touch events and can't seem to fix this problem.
Here is the code handling the touch event:
Slider.prototype.isSwipe = function(threshold) {
return Math.abs(deltaX) > Math.max(threshold, Math.abs(deltaY));
}
Slider.prototype.touchStart = function(e) {
if (this._isSliding) return false;
touchMoving = true;
deltaX = deltaY = 0;
if (e.originalEvent.touches.length === 1) {
startX = e.originalEvent.touches[0].pageX;
startY = e.originalEvent.touches[0].pageY;
this._$slider.on('touchmove touchcancel', this.touchMove.bind(this)).one('touchend', this.touchEnd.bind(this));
isFlick = true;
window.setTimeout(function() {
isFlick = false;
}, flickTimeout);
}
}
Slider.prototype.touchMove = function(e) {
deltaX = startX - e.originalEvent.touches[0].pageX;
deltaY = startY - e.originalEvent.touches[0].pageY;
if(this.isSwipe(swipeThreshold)) {
e.preventDefault();
e.stopPropagation();
swiping = true;
}
if(swiping) {
this.slide(deltaX / this._sliderWidth, true)
}
}
Slider.prototype.touchEnd = function(e) {
var threshold = isFlick ? swipeThreshold : this._sliderWidth / 2;
if (this.isSwipe(threshold)) {
deltaX < 0 ? this.prev() : this.next();
}
else {
this.slide(0, !deltaX);
}
swiping = false;
this._$slider.off('touchmove', this.touchMove).one(transitionend, $.proxy(function() {
this.slide(0, true);
touchMoving = false;
}, this));
}
You can find the actual slider here at this pen.
If you swipe through fast enough it will throw the error and sometimes get stuck in the middle of a swipe. Still can't wrap my head around why it is not working. Any help/insight would be greatly appreciated. Not sure what I am doing wrong.
The event must be cancelable. Adding an if statement solves this issue.
if (e.cancelable) {
e.preventDefault();
}
In your code you should put it here:
if (this.isSwipe(swipeThreshold) && e.cancelable) {
e.preventDefault();
e.stopPropagation();
swiping = true;
}
I know this is an old post but I had a lot of issues trying to solve this and I finally did so I wanted to share.
My issue was that I was adding an event listener within the ontouchstart and removing it in the ontouchend functions - something like this
function onTouchStart() {
window.addEventListener("touchmove", handleTouchMove, {
passive: false
});
}
function onTouchEnd() {
window.removeEventListener("touchmove", handleTouchMove, {
passive: true
});
}
function handleTouchMove(e) {
e.preventDefault();
}
For some reason adding it removing it like this was causing this issue of the event randomly not being cancelable. So to solve this I kept the listener active and toggled a boolean on whether or not it should prevent the event - something like this:
let stopScrolling = false;
window.addEventListener("touchmove", handleTouchMove, {
passive: false
});
function handleTouchMove(e) {
if (!stopScrolling) {
return;
}
e.preventDefault();
}
function onTouchStart() {
stopScrolling = true;
}
function onTouchEnd() {
stopScrolling = false;
}
I was actually using React so my solution involved setting state, but I've simplified it for a more generic solution. Hopefully this helps someone!
I had this problem and all I had to do is return true from touchend and the warning went away.
Calling preventDefault on touchmove while you're actively scrolling is not working in Chrome. To prevent performance issues, you cannot interrupt a scroll.
Try to call preventDefault() from touchstart and everything should be ok.
Please remove e.preventDefault(), because event.cancelable of touchmove is false.
So you can't call this method.
If it is an image, you can just set 'touch-action' to none in css.
ok... I might be a lazy one to search but it is a bit annoying that all I can find is
"how can i set scroll down event" when I searched "how do i prevent scroll down".
in my javascript code, I set event for down arrow key. When I press down arrow
from the browser, the browser not only does an event I set, but also does
scrolling down the page which is not I intended to. So here is my question.
How can I disable scroll down function which occurs when I press down arrow?
any help will be appreciated.
If you want to prevent the vertical scrollbar and any vertical scrolling action by the user, you can use this javascript:
document.body.style.overflowY = "hidden";
Or, this can also be set with a CSS rule:
body {overflow-y: hidden;}
On the other hand, if what you're trying to do is to prevent the default key handler for the down arrow from doing anything after you process the down array, then you need to call e.preventDefault() like this:
function myKeyDownHandler(e) {
// your code here
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false; // older versions of IE (yuck)
}
return false;
}
A cleaner way if you need to do this in more than one place would be to make your own cross browser function for this:
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false; // older versions of IE (yuck)
}
}
function myKeyDownHandler(e) {
// your code here
preventDefault(e);
return false;
}
This is one of those perfect examples where a cross-browser framework (jQuery/YUI/etc) saves you time because they've already done all this cross-browser work for you.
Here's an interesting article on preventDefault and stopPropagation().
Here is an example page that doesn't allow for the use of the arrow keys for scrolling:
<script>
document.onkeydown = function(evt) {
evt = evt || window.event;
var keyCode = evt.keyCode;
if (keyCode >= 37 && keyCode <= 40) {
return false;
}
};
</script>
<body style="height:3000px;">
</body>