Tap event with Google Maps API not received


#1

Hi everyone,

I’m new to this forum, so let me introduce myself first. I’m a software developer for a french company in security and I’m working on a mobile app (targeted for Android first, and then for iOS but later in the project) for civil aviation. I’ve been using Ionic for my project since 6 month now and I have to say that I love it!

Now here’s my problem. It’s been several days I’m stuck with it after having tried some many different thins and read a lot of post on this forum or to some place else. I am using Google Maps API within my application. More particularly I am showing a map inside a ion-content of a modal view. The purpose of this map is to let the user placing a marker on the map to select geographic coordinates.

After having created the modal and create Google Maps instance within it, I register event listeners for mousedown and mouseup on the map object. The purpose is to create a timeout on mousedown that will place a marker with a 1 sec delay and cancel this timeout (if not already triggered) on mouseup (to be exhaustive, I do the same on other event like dragstart to avoid placing a marker when user is dragging map, but I am omitting it here for simplicity purpose).

This just work fine when using Chrome on PC, but on my Android test device (Nexus 7 2013) or using Chrome on PC with DevTool and “device mode” enabled, it does not work properly. The fact is that any touch event received by application is first captured by Ionic framework that will kind of “disabling” next touch event within the 2 next sec. Meaning that when I tap down, my application receive the mousedown event, but when I tap up, the event is never received if it happen less than 2 sec after being tap down. It results from that than even if I didn’t tap for 1 sec, a marker is placed on the map. Moreover, if I’m continuously tapping for less than 1 sec, only the first tap event is received.

The element which Google Maps is binding to is declared with:

data-tap-disabled="true"

So that’s not my issue. I have deeply look into Ionic’s code and have found that it ionic.tap is neutralizing event with a 2 sec delay using the function below:

// ionic.bundle.js v1.0.0-beta13 line 2781
function tapEnableTouchEvents() {
  tapEnabledTouchEvents = true;
  clearTimeout(tapMouseResetTimer);
  tapMouseResetTimer = setTimeout(function(){
    tapEnabledTouchEvents = false;
  }, 2000);
}

I have commented that code into Ionic for test purpose and It works perfectly on both my Android device and Chrome DevTool in device mode but then I have some weird behavior in other parts of my app. So I want to understand what I am doing wrong? I’m sure that someone had already did this before in its app, so it may be possible. Is there something I forgot somewhere? Or maybe I’m totally wrong and that not the correct way to place a marker on map with a “long press”?

I’m not sure if it’s a Ionic or Google Maps issue so I’m asking for your help. Here is a CodePen of a very simplified version which just work perfectly on Chrome, but if you are using Chrome DevTools (by pressing F12 while on the page) and then enabling “device mode” (by clicking the phone icon on the top-left corner of DevTool and then reloading the page with F5), you will see that it does not work anymore. I put some console log on map mousedown and mouseup event so you can see that event are received when device mode is off but not when device mode is on:

Thanks in advance for your help.


#2

I played with it a bit on my phone. I could only get it to drop a pin if the map had not been touched for more than 3 or 4 seconds. If I moved the map or tapped anywhere, I had to wait 3 or 4 seconds to get the dropped pin to work. I’m not sure if that is Ionic. data-tap-disabled is supposed to remove all tap events for ionic.


#3

That’s what I thought too. But the fact is that the code I quote from Ionic bundle in my previous post of tapEnableTouchEvents() function is setting a boolean which, as its name may not show, disable the mouse down and mouse up events. Then it start a timer that trigger 2 sec after to set back this boolean to its initial value et reenabling those mouse event. This happens whatever the value of data-tap-disabled is.

The tapEnabledTouchEvents value that is set to true in ionic function is then used in two other functions: tapMouseDown(e) and tapMouseUp(e) which are function that ionic respectively bind to mousedownand mouseup events. Here is an extract of ionic code for mouseup event callback:

function tapMouseUp(e) {
  if(tapEnabledTouchEvents) {
    e.stopPropagation();
    e.preventDefault();
    return false;
  }
  ...
}

Here we clearly see that when tapEnabledTouchEvents value is set to true, the event is stopped right here. This function is directly bind by ionic framework to the DOM mouse event, so it is the first function called after having clicked. There is absolutely no check of the data-tap-disabled value. As I said in my previous post, I locally modified the Ionic script to comment the tapEnableTouchEvents() function body and then it works perfectly.

By the way, maybe it’s just me, but I don’t understand why all ionic’s code is talking about “tap enable touch event” as it actually disable them!


#4

I was having the same problem, that you need to wait 3 or 4 seconds (without touching the map) to do some other action. In my case I was doing:

google.maps.event.addListener(marker, 'touchstart', function() {

but then, I changed to:

google.maps.event.addListener(marker, 'click', function() {

And it works. I think the problem is using data-tap-disabled="true" and the touchstart event.

So, if you change:

google.maps.event.addListener($scope.map, "mousedown", function onGoogleMapsMouseDown(event)

to:

google.maps.event.addListener($scope.map, "click", function onGoogleMapsMouseDown(event)

it should work. That is my solution :smile: , if you still want to use mousedown, I don’t have an answer


#5

@matias : Nice - that did the trick for me. However, @amazaud wants to require the users to long press for a while. If they don’t press long enough, it shouldn’t put the marker.

@amazaud I don’t have a solution to this. You might want to consider opening an issue. http://ionicframework.com/submit-issue/


#6

The click event seams to not be affected indeed. I also tired the touchstart and touchend but it doesn’t work at all (none of those events seems to be captured by Google Maps API, neither on PC nor on mobile device).

To be honest, the workaround I’m using today is to place the marker on dblclick event which, as the click event, works perfectly, but I most not forgot to disable the “zoom on double click” feature at Google Maps map object creation by setting the disableDoubleClickZoom value to false when calling the google.maps.Map constructor.

But as @Calendee has well understood, I prefer the long press solution, because it is the default behavior in Google Maps standalone application or Apple Maps for iOS: long press to place a marker and double click to zoom. I think that is better to copy this behavior since users are “used to do like this”.

As recommended by @Calendee I opened an issue for that problem: https://github.com/driftyco/ionic/issues/2614

Thanks for your help to both of you, I’ll keep you in touch in that topic if I got any news.