I want to listen to pointermove event on IE11, but it seems that pointermove only fires for mouse (and possibly pen), but not when you are using your finger.
http://jsfiddle.net/qq2hjL2g/
Actually, the specification says that it fires for pens/mice, so this may not be really a bug.
But, is there any way to listen to pointermove on IE for touch? There must be, but I was very surprised to see pointermove not firing at all.
EDIT: I found that if I put CSS touch-action: none on the div, pointermove events fire. But why? I'm trying to find documents related to this, but I couldn't find any so far.
EDIT: I learend that the touch-action CSS specifies which touch actions are handled by the browser. This means setting touch-action to none tells the browser to not handle any touch events, and the developer is responsible for controlling the behaviour throutgh JavaScript events. This is why I was getting the events fired properly only when I had the CSS. (See more at MDN.)
I'm also trying to interface with IE11 touch.
I believe MSGesture is used for touch events because in their documentation they refer to "fingers"
http://msdn.microsoft.com/en-us/library/windows/apps/hh465856.aspx
http://msdn.microsoft.com/en-US/library/ie/hh968249.aspx
I believe the gestures you are interested in are:
MSGestureStart - "Triggered when the screen is touched on a location over this element."
MSGestureChange - "Triggered when the finger positions associated with the interaction moves on the screen."
MSGestureEnd - "This event fires when all associated contacts are removed from the surface"
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 developing a game in canvas that interprets "wheel" events as a command to zoom in/out on the scene. I was playtesting in Edge on my laptop when I realized that Edge was not firing "wheel" events while 2-finger scrolling on my precision touchpad.
After a little searching, I came across this official response from Microsoft which states: 'Microsoft Edge will fire Pointer Events with a pointerType of “touch” in response to PTP gestures'.
The problem is that these pointer events don't appear to exist. I added event listeners for all the pointer events and told them to log the event if it had a pointer type of "touch" but got no response (though they were triggered by the touch screen as expected). What confuses me more, is there doesn't seem to be pointer event activity of any type while making 2-finger gestures. So am I missing some non-standard event type or something? I'm pretty sure I haven't misread the article since a response to the loss of "wheel" event functionality appears to be the whole point of the work around and so leaving out events for two-finger gestures would defeat the point.
A few days later I tried again and managed to get ptp touch pointer events through
pointerdown
pointermove
pointerup
pointercancel
pointerout
Side note, "touch" pointers seem to be identical to those generated by touching the touch screen so if you need them to be distinguished like I did, you can exploit the fact that ptp gestures do not fire touch events to distinguish them.
Making a nice quick-responding website is relatively difficult because of the conflicts between touchstart, tap and the 300ms delayed click.
Ofcourse vclick should fix these issues, but also they seem to have problems fixing it completely. From the documentation:
Warning: Use vclick with caution
Use vclick with caution on touch devices. Webkit based browsers
synthesize mousedown, mouseup, and click events roughly 300ms after
the touchend event is dispatched. The target of the synthesized mouse
events are calculated at the time they are dispatched and are based on
the location of the touch events and, in some cases, the
implementation specific heuristics which leads to different target
calculations on different devices and even different OS versions for
the same device. This means the target element within the original
touch events could be different from the target element within the
synthesized mouse events.
We recommend using click instead of vclick anytime the action being
triggered has the possibility of changing the content underneath the
point that was touched on screen. This includes page transitions and
other behaviors such as collapse/expand that could result in the
screen shifting or content being completely replaced.
Now I'm thinking about doing something simpler. Whenever a touchstart event is being triggered I know this is a touch device for sure. I just disable all click events, and start listening to touchstart (or tap) events only. Ignoring the 300ms delayed click events.
Of course there are devices with a mouse and touch, but people using these at the same time seem like a minority to me.
Is this a good idea, or am I missing something in my thinking?
First of… what makes you say that people that use both touch and mouse input are a minority?
The 300ms click delay has been gone a while now on Android when using <meta name="viewport" content="width=device-width">. Unfortunately it can't be removed on iOS because it's a scroll gesture on unzoomable pages that almost nobody seems to be aware of.
I'd say that the best approach is still to support both mouse as well as touch input, despite the 300ms delay on iOS devices. It's dangerous to assume a user will exclusively use touch input when they use it once.
Imagine a user happily using a mouse to navigate. They see something interesting that they want to look at a bit closer so they use a touch gesture to zoom in and all of a sudden mouse clicks don't work anymore. That sounds broken to me.
I just remembered an interesting discussion about detecting a mouse user. Maybe it'll help you see things a bit differently.
Yes, in my honest opinion it is smart way to go. This has proven to be quite a hard problem and when you still combine it to the compatibility problems caused by some really crappy mobile devices which don't follow standards even that bit, it quickly becomes a battle that you can't win. We have adopted a solution close to this, with realization of fact that there might arise problems with poor devices. But after all, you can't satisfy the needs of everybody and the distribution of usage tends to favor those devices (nowadays) that follow the standards.
Also note that you don't need to wait for first touchstart to happen. Instead you can do this trick after DOM is ready and bind the events accordingly.
var isTouchDevice = 'ontouchstart' in document.documentElement;
which is copied from KevBurnsJr's answer.
Also as you most probably already know, you can bind to all kind of events and then check when entering the callback of which type the event actually is with
event.type
Good luck!
It would be a bad idea to disable all click events on the basis of a single touchstart as you suggest. While using both pointers or touch at the same time isn't a common use case. Preventing dual use of mouse/pens and touch isn't a forward compatible approach.
And when you say: "Ignoring the 300ms delayed click events."
I think you make a false assumption on click. You'd still have to synthesize clicks one way or another. touchstart alone isn't a click action. An assumed click happens on touchend, not touchstart. Here is the principle behind detecting clicks early on mobile: https://developers.google.com/mobile/articles/fast_buttons
If you are looking for fastclicks you may want to look into the fastclick script or other fastclick ones on github instead of vclicks.
To avoid issues with people using both touchscreen and mouse with pleasant reactivity I suggest this in JQuery, it works good enough for me:
$elem.on('click touchstart', function(e){
var $self = $(this);
if(e.type == 'touchstart'){
$self.mouseenter(); //fire events you still need
e.preventDefault();
}
/* your code */
});
From my experience it's better than keep the delay on click event and some hazardous comportment through devices, but there's inconvenient too.
On the iPad I tested, it avoids the situation where hover event is triggered on first tap then click event on second tap, but also it seems that the click event fire when you tap near the border of your element and not the touchstart, have to keep it in mind.
Also, it seems not working well with 'tap' event, certainly because it's not well treated yet by JQuery.
I'd assume this question has been asked to death, but I'm not finding anything good.
What I'd like is a unified set of events that span devices. I know the mapping isn't always 1 to 1, but just something that covers the basics like:
ignores/disables hover events/styles on a touch device
maps a touchstart to a mousedown
similarly, touchend to mouseup
tap to click
etc...
maybe even touch, hold 1s, touchmove to dragstart...
I haven't thought through all the specifics. And of course device specific events like hover on a desktop, or swipe on a tablet, can't be translated and should just be ignored if not supported.
Anybody know of a library that will do this. Preferably an invisible jQuery patch.
Thanks.
jQuery Mobile does exactly this, amongst many other things.
See their documentation on virtual mouse events, which:
... provide a set of "virtual" mouse events that attempt to abstract away mouse and touch events
I'm attempting to convert my web app into a form usable by mobile devices. I'm attempting to build in support for touch gestures like horizontal scrolling. I'm finding some strange behavior in my app.
I start a gesture with a touchstart event, and then scroll on touchmove. However, my application sees a 500-700 ms delay between receiving these two events. As far as I can tell, my app is doing no other work between these two events.
Other aspects:
The code is written in jquery, using
$(element).bind(touchmove, function(ev) {return myobject.DoTouch(ev) }
were the DoTouch command simply checks the ev.type, records the touch position, and returns false.
Any ideas what I should look for to try to solve this? The lag between touching and getting a response from the app is very annoying.
Yes. It turns out, this is how iOS works. I was pulling my own hair out for some time. Read more here: http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html. Essentially, if iOS thinks it can handle this as an internal PAN gesture, it does and doesn't even bother sending a touchmove event at all.
In my project, I found that if the viewer makes the touchmove gesture very deliberately and pauses a bit longer before lifting the finger at the end of the move, then the touchmove event is, in fact, sent as one might expect. So, the documented behaviour may be a little iffy versus reality, which only added to confusion and my debugging efforts.
Anyway, if iOS handles the event internally as a PAN gesture, it will send a scroll event before the touchend. In my project I was able to use this to set the flag I was using to distinguish dragging gestures (which was normally sent in my touchmove handler) and ignore any behaviour in stand-alone touchend handlers that were not related to the handling of my own scroll-handling.
I hope this helps you (and others) as well!