Closed dankarran closed 2 years ago
Minimal example reproducing the issue
For the sake of clarity: that example is using
L.DomEvent.on(container, "click", function(e) {
Would Leaflet be able to safely filter out the click events with
isTrusted:false
?
It would be possible to do so, in addOne()
in DomEvent.js
, around https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/dom/DomEvent.js#L109
With a new branch in that if-then-else chain, something probably like
} else if (Browser.safari && !Browser.mobile && type === 'click') {
handler = function (ev) {
if (ev.isTrusted) { originalHandler(ev); }
}
obj.addEventListener('click', handler, false);
} // etc
However, I do not own any Apple hardware (at the moment), so I'm unable to test this; and I don't know if this might impact previous versions of desktop Safari.
The simulated event comes from https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L100
So I suggest changing the condition at https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L87
into something like
if (this._fireClick && e && e.changedTouches && !(Browser.safari && !Browser.mobile)) {
However, I do not own any Apple hardware (at the moment), so I'm unable to test this; and I don't know if this might impact previous versions of desktop Safari, or other browsers (Does the bug maybe reproduce on firefox mobile?).
I think this bug has been introduced at
https://github.com/Leaflet/Leaflet/pull/7010/files#diff-c2e3d5ef35bf1c4a7c6b549ddf734725R134
@johnd0e , can you have a look? Maybe you introduced that change to account for iOS but unintentionally affected desktop macOS?
Thanks for looking into it @IvanSanchez. I'm happy to help testing any proposed changes on Safari on Mac or iOS.
Just to add, there is a related problem in Safari on iOS, but it seems to behave slightly differently. I haven't done much testing on that.
@johnd0e , can you have a look? Maybe you introduced that change to account for iOS but unintentionally affected desktop macOS?
That was definitely meant to address iOS issues, see discussion: https://github.com/Leaflet/Leaflet/pull/7010.
And we use safari
property intentionally, in order not to be tooo specific.
Possible quickfixes:
Browser.ios
propertyBrowser.safari && Browser.mobile
But what if tomorrow we will get macbook with touchscren? That will break it all again.
So I propose to apply quickfix (Browser.safari && Browser.mobile
) ASAP, and then discuss ultimate solution here: #6980
* or use `Browser.safari && Browser.mobile`
I like this approach (as a "quick & dirty" fix).
But what if tomorrow we will get macbook with touchscren? That will break it all again.
You know that my answer, in the end, is gonna be #7200 :-)
You know that my answer, in the end, is gonna be #7200 :-)
I am not so sure) But anyway, I'd prefer to fix all we can staying in current approach, and then move further (to #7200 or whatever).
Unsure whether this is the same issue (so please forgive tagging onto end of existing ticket), but shift-drag to zoom in is also broken in 1.7.1 on desktop Safari. Happy to open a new issue if #7260 hasn't fixed this too.
@systemed Can you please try shift-dragging using https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js ? (e.g. https://plnkr.co/edit/v4GzrCYSxpIO1aOo ) That's a build from master
that already includes the changes from #7260.
Spot on - that works fine. π
As appeared, the same issue affects not only desktop Safari, but also legacy Edge (and who knows what else).
AFAIK atm tap
handler is needed for iOS only.
So... May be we should change map.options.tap
default to false
.
I've updated my codepen to use the code built from master, and also to display the events to make it easier to test on mobile.
It's working well on desktop Safari, but unfortunately, it looks like mobile Safari is still firing off two click events.
If the JS at https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js is the latest version, it's still firing two click events on iOS Safari.
@dagjomar Are you able to inspect those events?
It may be different issue.
Because on touchstart
(and pointerdown
) we prevent click
here:
https://github.com/Leaflet/Leaflet/blob/dda26ba96d7dc79213818d1bcc0565b6ac3c69c4/src/map/handler/Map.Tap.js#L43
And I do not see any reason why that might not work.
@johnd0e I'll see if I can get some more details out, and let you know. Would it make a difference what type of element was used (e.g. a
or button
which would have their own click handlers vs div
which wouldn't)?
I've updated the codepen to log some simplified event details to the console on there. The events on iOS seem to be the same as seen on the desktop before this update:
type: click
isTrusted: false
composed: false
_simulated: true
webkitForce: 0
type: click
isTrusted: true
composed: true
webkitForce: 1
Also, a
and div
elements behave the same, and adding e.preventDefault()
in my event handler doesn't solve it.
Let me know if there's anything else you'd like me to try @johnd0e?
Is it possible that the following lines aren't needed, if Safari is firing its own click events?
By the way, I've just checked and Chrome (v85) on iOS is behaving the same, with two events fired.
Ok, see what I've found:
1) Preventing mousedown
/pointerdown
does not cancel click
. Only touchstart
can be prevented.
2) But currently Leaflet has rather weird behavior (#7077): when pointer events are available - it substitutes touch events with pointer events.
That's why we now have those extra clicks.
So to fix that properly we should adopt one of these: #7029, #7026. @IvanSanchez
If it helps as a quick fix as a stopgap (and doesn't break other things), commenting out that simulated event does seem to work for me in both Chrome and Safari on iOS...
@systemed Can you please try shift-dragging using https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js ? (e.g. https://plnkr.co/edit/v4GzrCYSxpIO1aOo ) That's a build from
master
that already includes the changes from #7260.
https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js
^ this version seems to work way better than 1.7.1
in desktop Safari 14.0.
tap or click fires only once π
If it helps as a quick fix as a stopgap (and doesn't break other things), commenting out that simulated event does seem to work for me in both Chrome and Safari on iOS...
I had the 2 click event issue on all device (desktop firefox, chrome, ios safari, chrome..) and this resolved the issue
The same problem happens to me and only happens in Safari. Chrome and Firefox are only firing the event once MacOS 10.15.6 and Safari 14.0.
I temporarily downgraded Leaflet to 1.6 and everything works normally.
Is there a chance this bug will be fixed? Does anyone work on it?
As I've already said: the bug is caused by extremely outdated tap
handler (#6980).
To get things off the ground we need to make some decisions: https://github.com/Leaflet/Leaflet/issues/7255#issuecomment-691109158 @IvanSanchez @mourner
To get things off the ground we need to make some decisions: #7255 (comment)
@johnd0e I don't have neither the time to test this, nor any iOS hardware. Anyhow, I'm trusting you on this, so I'm greenlighting #7026 (which feels cleaner than #7029)
Does anyone work on it?
You know what'd be cool, @PeterPan73? For you to go ahead with making a couple of builds from #7026 and #7029, and testing those for further compatibility issues, instead of just putting more pressure on the maintainers.
so I'm greenlighting #7026 (which feels cleaner than #7029)
Unfortunately in last commit of #7026 I had to apply ugly workarounds in order to overcome other bugs (which in turn can be addressed by #7029 and #7059).
So in the end we still will have to deal with #7029 and other connected PRs, that's why I've united them all under https://github.com/Leaflet/Leaflet/projects/1
I run into this issue on macOS 10.15.7 using Chrome 85 DevTools with iOS device enabled. The quickest workaround for me has been to use lodash debounce
function.
Today I ran into an issue, which seems connected to this one, so I will post my experience here.
This occurs with the Macbook trackpad and I discovered it, when trying to add a custom contextmenu to the map.
What happens is that, once the map has focus, even if you right click for the contextmenu, Leaflet will fire a simulated click event, which should not be fired and has button
value 0. This leads to weird interactions with my close handler for the contextmenu.
To produce the bug you can go to https://leafletjs.com and then:
What you will see is that the cursor is in dragging mode and once you twice click on the map (once the close contextmenu and once to trigger click event) the map will jump.
Maybe this relates also to some other issues (e.g. #6865).
This twice click event (one trusted, one not) occurs for me on 1.7.1 when simulating mobile on Chrome and Firefox on desktop Linux (didn't happen on 1.6). Works well on real Android touch devices though (Chrome/Firefox tested). I have for now solved it by implementing my own bounce timer in the click event handler, filtering out clicks that happen within 150 ms from the last one.
I have for now solved it by implementing my own bounce timer in the click event handler, filtering out clicks that happen within 150 ms from the last one.
Hi @atorger, how did you implement this? I tried event.originalEvent.preventDefault();
in the onClick event handler, but with no success. Can you share a minimal example? π π
I have for now solved it by implementing my own bounce timer in the click event handler, filtering out clicks that happen within 150 ms from the last one.
Hi @atorger, how did you implement this? I tried
event.originalEvent.preventDefault();
in the onClick event handler, but with no success. Can you share a minimal example? pray smile
sure:
var lastClick = Date.now();
e.addEventListener('click', function(event) {
var now = Date.now();
var diff = now - lastClick;
lastClick = now;
event.stopPropagation();
if (diff > 150) {
// handle the click event
}
});
Note that this issue also causes bindPopup
to not work with markers:
I ran into this problem in firefox as well (and mobile safari). I was not able to reproduce it reliably but the hint that it comes from the tap option led me to the solution which disables tap entirely as I apparently don't need it to open the popup, even on mobile safari:
var map = L.map('map', { "tap": false });
I ran into this problem in firefox as well (and mobile safari). I was not able to reproduce it reliably but the hint that it comes from the tap option led me to the solution which disables tap entirely as I apparently don't need it to open the popup, even on mobile safari:
var map = L.map('map', { "tap": false });
Thank you for this solution, @eikes! I ran into this issue today and that solved it.
I apparently don't need it to open the popup, even on mobile safari:
On mobile safari tap
handler is needed to simulate contextmenu
event on taphold.
This bug fires two touches when trying to click on map on a mobile device.
I can confirm. Multiple users have reported popups not working on iOS / Safari on our map using Leaflet 1.7.1
See https://github.com/domoritz/leaflet-locatecontrol/issues/280 and the workaround that fixes the issue.
This issue prevents menus from working on Safari. For example, openstreetmap loses its map tools. As no one is assigned to this bug, it may not get attention.
Today I faced with the same bug on the last version of the iOS. Popup appears and closes instantly due to duplicate click.
disabling tap altogether fixes this for me on safari (using leaflet from react-leaflet) and all my tap events still work.
var map = L.map('map', { "tap": false });
works great! Not sure what "tap" actually does since my markers, panning etc all still work.
edit: says @eikes comment was pinned but I actually had to "unhide" it to see it
Disabling tap fixed the problem for me also. But since I'm using React-Leaflet, I don't use L.map()
. Instead, the MapContainer component has a tap
prop that can be used for disabling tapping.
<MapContainer tap={false}>
For anyone using Vue-Leaflet, setting tap to false seems to work to resolve the issue, but remember that vue-leaflet only allows some options to be passed as props to the map component directly, for the rest (like 'tap') you need to pass a custom 'options' object, as per: https://vue2-leaflet.netlify.app/faq/#how-can-i-specify-leaflet-options-that-aren-t-part-of-a-component-s-props
@johnd0e @IvanSanchez is there now a fix merged or is this still open?
Hi! I've read through this thread and I see several notes about this being fixed from the discussions when the thread first started back in 2020 to more recently.
I am still seeing this happening on Safari Desktop. Is this expected ?
Thanks Justin
@justinjngan see https://github.com/Leaflet/Leaflet/issues/7255#issuecomment-955691965.
Steps to reproduce Steps to reproduce the behavior:
isTrusted:true
and another withisTrusted:false
attributes(Using 'force touch' to click the button on a trackpad results in only a single click event being emitted, but it also triggers the Safari preview popup.)
Expected behavior
There should only be one click event emitted, with the
isTrusted:true
attribute.Would Leaflet be able to safely filter out the click events with
isTrusted:false
?Current behavior
In version 1.6 the expected behaviour is observed. In version 1.7.1 Chrome exhibits the expected behaviour, but Safari doesn't.
The differences between the two events are included below.
MouseEvent 1:
MouseEvent 2:
_simulated
,composed
,isTrusted
and perhapswebkitForce
seem to be the key differences, but it also seems odd that there are different timestamps and Y dimensions between the two events.Environment
Additional context
I noticed this after OpenStreetMap updated to the latest version of Leaflet, where the issue manifests itself by preventing some of the map tools to be used as the first event toggles a tool on and the second toggles it off. Related issue posted at https://github.com/openstreetmap/openstreetmap-website/issues/2811
Minimal example reproducing the issue
Please see https://codepen.io/dankarran/pen/JjXMXzd