I'm creating a website for my friends to allow them to play a higher quality online implementation of Hashiwokakero.
Some of them have tablets, and everything on the website loads perfectly fine, but when they go to touch and drag to form a bridge from one island to another, the webpage tries to scroll instead (even though there is no scrollable area!).
Currently I am detecting mouse events using the following:
this.canvas.addEventListener('mousedown',
(mouseEvent) => this.mousePressed(mouseEvent), false);
this.canvas.addEventListener('mouseup',
(mouseEvent) => this.mouseReleased(mouseEvent), false);
Is there a simple way I can go about having my mousePressed() and mouseReleased() functions invoked on mobile?
Thanks!
Similar events for touch screens will be touchstart and touchend, they are totally the same as mousedown and mouseup events for desktop. From docs:
The touchstart event is fired when one or more touch points are placed
on the touch surface.
and
The touchend event is fired when one or more touch points are removed
from the touch surface.
You can check docs for more info about touch events.
I also guess that may be you will also need to stop some events from bubbling, and if so, you can take a look at events bubbling and event.stopPropagation() to prevent them from bubbling.
If the logic should be the same for both mousedown/touchstart and mouseup/touchend events, you can bind multiple events to the listener as described here.
Related
is there a touch equivalent of the mouseenter.
I would like to detect if user slide on my DIV.
I prefer a solution depending directly on the target element not on a parent element with recounting positions etc.
The site: http://dizzyn.github.io/piano-game/ - works fine with mouse (mouse down and slide; not working with touch slide)
Thank you
2019: Yes-ish: Using pointerenter.
BUT, by default, a touch (or mouse down) causes the element to 'capture' the pointer, preventing further pointerleave/enter events unless you explicitly release the capture.
Moreover, you'll want to set touch-action:none on relevant elements to avoid the browser intercepting touches for default pan/zoom etc.
Example:
CSS:
*{ touch-action: none; }
JS:
let div = document.querySelector("div")
div.addEventListener("pointerdown",(e)=>{
console.log("down")
console.log("attempt release implicit capture")
div.releasePointerCapture(e.pointerId) // <- Important!
})
div.addEventListener("pointerenter",(e)=>{
console.log("enter")
})
div.addEventListener("pointerleave",(e)=>{
console.log("leave")
})
Works in Chrome at least. Not so much in Mobile Safari 13 beta though... According to the w3c specs, I'm fairly certain it should work this way. Maybe when iOS 13 is officially released we'll be in the clear. [I've filed a bug and looks like it's being attended to.]
[Update: iOS 13 issue fixed. Should work in Chrome/FF/Safari]
Look into these events:
touchstart Triggers when the user makes contact with the touch surface and creates a touch point inside the element the event is bound to.
touchmove Triggers when the user moves the touch point across the touch surface.
touchend Triggers when the user removes a touch point from the surface. It fires regardless of whether the touch point is removed while inside the bound-to element, or outside, such as if the user's finger slides out of the element first or even off the edge of the screen.
touchenter Triggers when the touch point enters the bound-to element. This event does not bubble.
touchleave Triggers when the touch point leaves the bound-to element. This event does not bubble.
touchcancel Triggers when the touch point no longer registers on the touch surface. This can occur if the user has moved the touch point outside the browser UI or into a plugin, for example, or if an alert modal pops up.
Specifically touchenter and touchleave.
Source: http://www.javascriptkit.com/javatutors/touchevents.shtml
For anyone who is trying to handle touch events in a web app here is helpful documentation W3C - Touch Events which explains the events in detail and how they are handled.
WC3 states:
If a Web application can process touch events, it can intercept them, and no corresponding mouse events would need to be dispatched by the user agent. If the Web application is not specifically written for touch input devices, it can react to the subsequent mouse events instead.
In short:
You can merely handle mouse events relative to touch events instead of handling both touch and mouse events.
I just wanted to say thank you to the previous poster. His suggestion worked perfectly. And I've been struggling to find a solution to this for weeks. If you're using Svelte within your pointerdown handler function I would suggest using:
const pointerDownHandler = (event) => {
// whatever logic you need
event.target.releasePointerCapture(event.pointerId);
}
He's accurate in saying this part is key. It will not work without it.
Answered this at Touchenter/Touchleave question.
Check please.
https://stackoverflow.com/a/61179966/835753
I will make a shot clarifying for Ian's answer:
Equivalent for mouseenter event is pointerenter event. But it will not work out of the box. To make it work you should:
Add to parent element pointerdown event listener with releasePointerCapture method
div.addEventListener("pointerdown",(e) => e.target.releasePointerCapture(e.pointerId))
Add to parent and to your element touch-action: none CSS property.
Enjoy :)
I have horizontally scrolling panel (via overflow-x:scroll) and user should be able to scroll it by dragging (not just scrollbar, but the content itself too).
Using some draggable carousel library (e.g. owlcarousel) isn't an option as all of them use transforms instead of native scroll.
So my plan is:
bind mousedown event
change horizontal scroll offset on mousemove
stop all actions at mouseup
All is good on desktop. But the problem is mobile, as mobile browsers trigger fake mousedown and mousemove events - the scrolling is corrupted. If I call preventDefault in touchstart/move - fake mouse events stop firing, but pane isn't scrolling either.
Is there any way to prevent fake mousedown/move/up events on mobile without calling e.preventDefault()?
Thanks for any input!
Quoting W3C:
To avoid processing the same interaction twice for touch (once for the touch event, and once for the compatibility mouse events), developers should make sure to cancel the touch event, suppressing the generation of any further mouse or click events. Alternatively, see the InputDeviceCapabilities API for a way to detect mouse events that were generated as a result of touch events.
Unfortunately this doesn't seem to be available in any browser (yet?).
A more viable possibility is to disable touch scrolling on your element, and letting your mouse handling code take care of the scrolling:
.my-panel {
touch-action: none;
}
If this makes scrolling too janky on mobile, a hacky but possibly effective solution might be to ignore any mousemove event that follows shortly (say, within 100 ms) after a touchmove event.
I am building a page that needs to work with touch and mouse interaction on PC, Mac, and mobile browsers.
In the event handler methods for touchStart, touchMove, touchEnd, and touchCancel I am calling event.preventDefault to prevent mobile browsers from firing both touch and mouse events.
This works great for mouseDown and mouseUp, which do not get fired when I touch the screen, but for some reason a short while (couple 100ms) after each touchStart is fired, the android browser still fires a mouseMove event (on the very first touchStart, this mouseMove is preceded by a mouseOver). If I touch quickly enough, the mouseMove gets fired after touchEnd (with the same delay relative to touchStart).
I'd really like to prevent any mouse events from being generated from touches and I'd also like to understand in detail what's going on here, so I have the following questions:
Is there some other touch event that I am not capturing which causes the mouseMove event?
Why is the mouseMove delayed a bit relative to the touch start?
Why isn't the mouseMove generated by any other touch events (touchMove, touchEnd)?
Do any other browsers have quirks that might generate mouse events from touches?
Is there a different cross-platform approach for preventing touch to cause mouse events? Maybe some CSS?
I have a larger problem with swipes not being registered. And I believe its because the SDK's assume you would want to click an drag the entire viewport of Safari instead of any of the divs that could be in it.
How can I prevent this default?
I believe you want to listen for the touchmove event and call event.preventDefault() therein on any elements you don't want to contribute to viewport movement.
jquery example:
$('.interestingElements').on('touchmove', function(event) {
event.preventDefault();
});
In mobile safari, the default behavior for a touchmove involving a single touch is to slide the viewport around.
If two touches are involved, the default behavior is to trigger a gesture event. Preventing default on touchmove prevents the gesture event from ever firing. You can use the changedTouches array to find out how many touches are involved in this touchmove event. Good luck!
Where can I find documentation or a reference for touchscreen events in Javascript, ex. "touchstart".
I found this useful link http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ (EDIT: page no longer exists) where the events "touchstart", "touchmove" and "touchend" are mentioned for IPhone.
Are there more? What about Blackberry and Android? I did not find much on SO and Google.
Edit
Here is a good documentation by Apple: https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
I used this site when developing a mobile web app http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/
But with research I have gotten a decent list.
touchstart
Action: fires when the screen is touched (will fire for multi-point touches as well)
Equivalent: mousedown
touchend
Action: fires when a finger is lifted from a screen (is really finiky with single point touch
Equivalent: mouseup
touchmove
Action: fires when one or more fingers move on the screen
Equivalent: mousemove
touchcancel
Action: when a touch event is canceled by the system
Equivalent: none that I'm aware
Other touch devices map the touch events to mouse events. Others ignore touch events.
To a Google API discussion - "Apart from mobile safari, there isn't a way to access touch events on
desktops that have a touch screen."