ngx-contextmenu
ngx-contextmenu copied to clipboard
Added touch compatiblity
If you're interested, I've added basic touch functionality so it works on phones/tablets.
First, thanks for contributing!
So basically, the context menu shows up when you long press? Is there not a native event for a long press? I'd like to avoid hard coding the time you have to press.
I haven't done much mobile web app development, so your input is appreciated.
Hi, thanks for replying so quickly!
Unfortunately there’s no such thing as a native event for long press from what I’ve found so far. There’s four options: touchstart, touchmove, touchcancel (when you receive a call for instance) and touchend that are shared between iOS and Android, according to MDN.
I understand your reluctance against hard-coding anything, I have the same sentiment. Half a second seems long enough to not be a click and short enough not to hamper any other function. I’ve scoured Stack Overflow of course, so this was the median I got to.
Greetings, Auke
Thanks for explaining the long press implementation.
What's the reason for falling back to pageX
/pageY
? Do mobile browsers not use clientX
/clientY
?
No, the touch event doesn’t even have a clientY/X param. So this was the next, and seemingly only available, thing.
I'm learning this stuff now, but it looks like the right thing to do is to reference the touches property of the TouchEvent
and then reference clientX
/clientY
on that. What should happen if there is more than one Touch
in the touches
array? Should we only use the first one? Or not open the context menu?
It looks like pageX
/pageY
is not supported in iOS Safari (TouchEvent inherits from UIEvent)
Also, even if the pageX/Y
events were supported, they'll position the context menu incorrectly. pageX/Y
is relative to the document, clientX/Y
is relative to the viewport.
That’s odd, I tested it on my iPad. I’ll have to look into it more to answer your questions.
I'm going to see if I can use TouchEvent instead of the current MouseEvent and test it on several android devices, ranging from 4.4.1 to 7. Or whatever is on a Galaxy S8. (Yay for test-material at work)
I've implemented the TouchEvent now, and cancelled out the touchmove event.
However.
I noticed that there's an obvious drag delay now only on the place with the touchmove hostbind, but I can't seem to find a way right now how to prevent this yet. Although I have some ideas.
After some serious testing across devices, I've noticed excessive inconsistencies among the different devices.
Android: Seems to ignore touchmove completely, instead registers a touchcancel on move, and fires the the contextmenu event, without touchend, after the standard duration.
iOS: Uses touchstart, touchend and touchmove. However, the default iOS context menu is opened regardless and seemingly is not part of the touch events available. The contextmenu event is never called.
I'm quite at a loss at the moment how to get this working.
Thanks for working on this. Cross browser/device testing is hard. I've avoided working on the mobile piece because it is so hard. My advice would be to find another library that handles touch events in javascript (not necessarily in Angular) and see how they handle all the device differences. This has to be a problem that other people have tried to solve before.
Let me know if I can help.
Here is the jQuery mobile taphold event implementation. And the custom events, vclick
etc are defined here.
It looks like they start a timer when touchstart
happens and if it hasn't been canceled after 1000ms the taphold
event is fired. Timer cancelling happens with a touchmove
, touchcancel
or touchend
.
I'm not planning to work on this myself, but if @Gizrah or someone else wants to pick up here and get something working I'd be glad of any contribution.
I think the Angular Material team is using HammerJS to handle longpress events. See the tooltip docs and the code. It looks like the (longpress)
event is set up here. Still don't quite understand how it works, but it looks like they've solved this problem.
I'll pick this up at a later date, when my current project is on the production environment. I can .. ehm .. sneak work on this in the meantime. Thanks for the documentation links!