I am using jquery, but I don't want to use jquery mobile, because it is so large, and I don't think I need it. All I am trying to do is get a touch event. This is what I've got.
$('#menuButton').on('click touchstart', function(){
$('#menu').toggleClass('block')
});
It only kind-of works, but seems to be firing twice a lot on my phone. I think I should check for both touchstart and touchend somehow. This needs to work on all types of devices, hopefully. Thanks!
Behold! The lifecycle of a touch:
your finger hits the glass -> touchstart!
your finger leaves the glass -> touchend!
your finger it lingers -> click!
Now the lifecycle of a mouse click:
your finger depresses the button -> mousedown!
your finger it removes pressure from the button -> mouseup!
your finger it lingers -> click!
If you are listening for both touchstart and click, the event will fire once on mouse or trackpad computers, and twice on touch devices as you are listening for 2 events in the lifecycle.
If you really want to use click for desktops and touchstart of touch devices (a good idea in many cases), you can do something like this:
var clickEvent = (isMobile)?'touchstart':'click';
$('#menuButton').on(clickEvent, function(){
$('#menu').toggleClass('block')
});
How you go about finding isMobile is another story.
update : I've written a handy script for detecting mobile, if your interested its npm isMobile
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'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.
I have a slider that works user drag it.
It works well on computers. but nothing happen in mobile browser.
So I want to handle drag by touches in mobile phones.
thanks.
You'd most likely want to use touchstart touchmove and touchend. Other mouse events like click will still work.
I am porting a piece of code for an HTML5 app from iOS/Android to Windows Phone 8. In this App there is a vertical scroll view with a number of elements.
In the original App I use "touchstart" and "touchend" events. This means every time the user touches the List I get a touchstart event, and even after scrolling around, when the user lifts the finger I get a touchend.
The MSPointer model works different. There is MSPointerDown which is the exact equivalent of touchstart, so no problem on this end.
I can't get my head around how to model the touchend behaviour though. MSPointerUp is not enough because it is only thrown if the user lifts its finger inside the same container where the MSPointerDown occurred. So if a user touches the list, then swipes it up and then lifts the finger, the event will not be fired. There is also MSPointerOut, which triggers when a user leaves the container where MSPointerUp was fired, the problem here is, it fires as soon as the container is left (so during the scrolling of the list) and doesn't fire after the user lifts its finger.
I'm a bit on a loss here how to model a "touchend" with MSPointer that will trigger in exact the same way as the Webkit one.
Cheers
Tom
This is the way I handle this issue.
Even though the Down/Move listeners are attached to some element, I attach the Up listener to the window.
This means that no matter where on the screen the user lifts the finger/pen/mouse (even outside the browser window in IE on a PC), the Up event is triggered.
This also means that you must handle all Up events in your app in one function. But you can set a flag (some global variable) on an element's Down event, and check for that flag in the UP event.
I've been doing this for a long time for mouse events on PC web pages, to handle when the user let's go of the mouse button outside the browser window.
It's annoying when they don't do this, like in Google Maps Street View where you're trying to pan around far and have to move the mouse a lot, and you let go of the button outside the window but it still thinks you're dragging.
I am currently working on the redesign of a website following the responsive design + mobile first approach.
I am trying to detect swipe events using JS on touch-enabled devices. For this purpose, I am using the following code:
document.addEventListener ('touchstart', function(event) {
//Get initial finger coords
}, false);
document.addEventListener ('touchmove', function(event) {
//Update final finger coords
}, false);
document.addEventListener ('touchend', function(event) {
//Compare initial and final coords, trigger swipe events if necessary
}, false);
I have tested this code on an iPad 1, an iPhone 4 and several devices running Android 2.2.1, and the result when I drag my finger on the screen is what I am expecting: the touchmove event fires several times (it can easily rise up to a hundred when doing a long gesture).
The problem comes when I test it on an Android 2.3.3 device (I'm using a Samsung Galaxy S2). Using its native broswer, the amount of touchmove events is reduced to only 1 (or rarely 2).
Am I doing something wrong or is it supposed to behave like that? Has anybody found the same problem? I was unable to find documentation about the behaviour of touchmove events in this version of Andriod.
You can test it here (using a touch-enabled device): http://jsfiddle.net/xs5BG/embedded/result/
It seems that galaxy S2 doesn't fire the touchmove after the scrolling starts to work. If you do a preventDefault it fires the events as expected.
Testing your jsFiddle example with my HTC Desire Z (running 2.3.3) i get many more than just one touchmove event - as desired. So i am unable to reproduce your actual problem with this device, although on the same API Level :( Interestingly enough your code also shows the problem that i am experiencing on my current project: The first touchmove event seems to have some kind of a threshold:
Putting the finger down and only moving a tiny bit will give 0 touchmove events... once over the threshold it will trigger touchmove events in intervals of milliseconds as it then recognises each and every pixel distance of a move (like it should do). Maybe this could be related to your phenomenon, respectively do you see this on your 2.3.3 device as well?
On many android versions if you don't preventDefault on touchstart the Android device will go into default scrolling mode and stops sending touch events to webview. So you would need to
document.addEventListener ('touchstart', function(event) {
event.preventDefault();
}, false);
Now all the touch events will fire, but default scrolling will be disabled.
There is a shim to overcome this issue that emulates a swipe gesture https://github.com/TNT-RoX/android-swipe-shim