How can I make an entire row clickable? [duplicate] - javascript

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 :)

Related

How to get 'pointermove' events in Edge and IE 11? [duplicate]

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"

Is disabling all click events at first touchstart event a good idea?

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.

MSPointer equivalent for "touchend"

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.

How can one prevent the ability to click and drag the viewport for safari on iPad or iPhone?

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!

unifying touch and click events

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

Categories

Resources