Handling together marker click and doubleclick on googlemaps - google-maps

I have the following problem.
On my google map app I need to distinguish click and doulbe click on the markers.
So when I am creating markers I create two listeners:
google.maps.event.addListener(markerTMP, 'click', (function(routeID) {
return function() {
console.log('click '+routeID);
}
})(pointRoute));
google.maps.event.addListener(markerTMP, 'dblclick', (function(routeID) {
return function() {
p('double click '+routeID);
}
})(pointRoute));
The problem is that when I use double click, click is also used.
My idea how to handle this:
On click - create a timeout, on double click - delete it.
But is there a normal way to handle this?
I was not able to found it in API reference.

Here is my workaround. it uses a global var to work across the two functions. Not the most eloquent, but works.
google.maps.event.addListener(marker, 'click', function() {
x = 0
update_timeout = setTimeout(function(){
if (x == 0) {
// do something ;
};
}, 300);
});
google.maps.event.addListener(marker, 'dblclick', function() {
x=1
// do something ;
});

There is no "official" way to handle this in the API. Creating a timeout seems to be the accepted approach.

Try using a click event and a rightclick event instead of click and dblclick.

Related

Google maps on mobile with gestureHandling = cooperative still fires click event

When on a mobile device, if I want to scroll the page by clicking somewhere on the Google map and scrolling down, I still receive a click event.
I see the "use two fingers to move the map" message, and the page is scrolling as expected but I receive a click event after. And I use this click event to add a marker. So at this point, it's messing the behavior of the whole page.
Here is a simple jsfiddle to reproduce (on mobile of course, or in mobile mode on chrome https://developers.google.com/web/tools/chrome-devtools/device-mode/):
Just scroll down while clicking on the map and an alert with the text "Click Event" will popup.
google.maps.event.addListener(map, 'click', function (evt) {
alert("Click Event");
});
https://jsfiddle.net/83o1my1p/
I believe this problem has already been reported in Google issue tracker. Have a look at the following bug:
https://issuetracker.google.com/issues/64586414
Feel free to add a star in the bug to express your interest and subscribe to notifications. Also, note that the person who filed the bug also found a workaround:
The clicks can be prevent after the scroll, the same way they they are prevented after dragend events when using on a desktop. As I said above, I worked around it myself by handling the mousedown event, and comparing the location of it, to the location of the click event.
I hope this helps!
Here is the work around I used.
var mouseDownPos = null;
google.maps.event.addListener(map, 'mousedown', function(e) { mouseDownPos = e.pixel });
google.maps.event.addListener(map, 'click', function(e) {
var mouseUpPos = e.pixel;
var distance = Math.sqrt(Math.pow(mouseDownPos.x - mouseUpPos.x, 2) + Math.pow(mouseDownPos.y - mouseUpPos.y, 2));
if(distance > 10) return; // Adjust for tolerance
// Do what you need here
});
My solution is to use a var and change it state on touch events. Then use it in the click event:
var dragged = false;
google.maps.event.addListener(map, 'click', function (evt) {
if (!dragged) {
// Do stuff here
}
});
google.maps.event.addDomListener(canvas, 'touchmove', function (event) {
if (event.touches.length == 1) {
dragged = true;
}
});
google.maps.event.addDomListener(canvas, 'touchend', function(event) {
dragged = false;
});

Bring GoogleMaps InfoWindow to front

I have a GoogleMaps APIv3 application in which multiple InfoWindows can be open at any one time. I would like to be able to bring an obscured InfoWindow to the front of all other InfoWindows if any part of it is clicked - similar to the behaviour of windows in MS Windows OS.
I had thought to add an onclick event handler which increases the z-index of the InfoWindow, but the event handler does not appear to be firing.
ZIndex is a global variable that keeps increasing as InfoWindows are clicked - or thats the theory anyway.
Can anyone help ?
Here is my code:-
var ZIndex=1;
var iw = new google.maps.InfoWindow({ content:contentString });
google.maps.event.addListener(iw, 'click', handleInfoWindowClick(iw) );
function handleInfoWindowClick(infoWindow) {
return function() {
infoWindow.setZIndex(ZIndex++);
}
}
there is no click-event for an infoWindow, it's a little bit more difficult.
you'll need to use an element(not a string) as content for the infowindow, because you need a DOMListener instead a listener for the infowindow-object
when domready-fires, you must apply the click-DOMListener to the anchestor of this content-node that defines the infowindow
The following code will do this for you, add this to your page:
google.maps.InfoWindowZ=function(opts){
var GM = google.maps,
GE = GM.event,
iw = new GM.InfoWindow(),
ce;
if(!GM.InfoWindowZZ){
GM.InfoWindowZZ=Number(GM.Marker.MAX_ZINDEX);
}
GE.addListener(iw,'content_changed',function(){
if(typeof this.getContent()=='string'){
var n=document.createElement('div');
n.innerHTML=this.getContent();
this.setContent(n);
return;
}
GE.addListener(this,'domready',
function(){
var _this=this;
_this.setZIndex(++GM.InfoWindowZZ);
if(ce){
GM.event.removeListener(ce);
}
ce=GE.addDomListener(this.getContent().parentNode
.parentNode.parentNode,'click',
function(){
_this.setZIndex(++GM.InfoWindowZZ);
});
})
});
if(opts)iw.setOptions(opts);
return iw;
}
Instead of google.maps.InfoWindow() you must call now google.maps.InfoWindowZ()
It also returns a genuine InfoWindow, but with the mentioned listener applied to it. It also creates the node from the content when needed.
Demo: http://jsfiddle.net/doktormolle/tRwnE/
Updated version for visualRefresh(using mouseover instead of click) http://jsfiddle.net/doktormolle/uuLBb/

Google Map API V3 — How to prevent mouse click event for a marker when user actually has double clicked

I have a marker on the map to which I want to bind two events:
click
dblclick
I want to do the following:
When user clicks on the marker, map should zoom-in and will show
more detailed map.
I want to bind 'dblclick' event to the same marker so that it will
load some third-party reports in adjacent 'div' element.
In other words, I want it to behave differently when user clicks or dblclicks. But the problem is, when I bind both these event to marker and user 'double clicks' the marker, 'click' handler is getting fired, which I don't want to let it happen.
Is it true that, when user double-clicks, click event is also fired? If so, how to prevent it from triggering 'click' event when user actually double-clicked?
Is there any way so that I can do different things on either click and double-click event of the marker?
It's a known nuance of the api, you need to install a click counter timeout, like this:
function createMap2() {
var infoWindow = new google.maps.InfoWindow();
var map = new google.maps.Map(document.getElementById("map2"), myOptions);
var doubleClicked=false;
var clickEvent;
google.maps.event.addListener(map, 'dblclick', function(event) {
doubleClicked=true;
});
function handleClick() {
if (!doubleClicked) {
infoWindow.setPosition(clickEvent.latLng);
infoWindow.setContent(createInfo(clickEvent));
infoWindow.open(map);
}
}
google.maps.event.addListener(map, 'click', function(event) {
clickEvent = event;
doubleClicked = false;
window.setTimeout(handleClick, 250);
});
}
Above code extracted from http://www.william-map.com/20100506/1/v3click.htm
Check out these links for more info:
https://groups.google.com/forum/?fromgroups=#!topic/google-maps-js-api-v3/YRAvYHngeNk
https://groups.google.com/forum/?fromgroups=#!topic/google-maps-js-api-v3/2MomDiLMEiw
You can use a pre-handler function that separates single from double clicks. In this case, the second click must come within 500 miliseconds of the first one:
//Global vars
var G = google.maps;
var clickTimeOut = null;
G.event.addListener(marker,'click',mClick);
function mClick(mev) {
if (clickTimeOut) {
window.clearTimeout(clickTimeOut);
clickTimeOut = null;
doubleClick(mev);
}
else {
clickTimeOut = window.setTimeout(function(){singleClick(mev)},500);
}
}
function doubleClick(mev) {
// handle double click here
}
function singleClick(mev) {
window.clearTimeout(clckTimeOut);
clickTimeOut = null;
// handle single click here
}
mev is the mouseEvent object that the event handlers receive as parameter.

Do not fire 'zoom_changed' event when calling fitBounds function on map

Is there a way to prevent the zoom_change event from being triggered if it occurs due to fitBounds() ?
I am having an issue where I need to do a search on the server from client when there is a zoom change to map but every time I call fitBounds() it causes zoom_change to trigger which causes the client to do another search on the server. I am only interested in zoom_change done by users and not programmatically using fitBounds.
When you do a fitBounds in your program, set a global flag. When the zoom_changed event fires, if the flag is set, clear it, otherwise send your request off to the server.
After many frustrating hours, here is my solution:
var tiles_listener = google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
var zoom_listener = google.maps.event.addListener(map, 'zoom_changed', function() {
reloadMarkers();
});
});
Note that I am calling addListenerOnce for tilesloaded to ensure that the zoome_changed listener is only added once, after the first fitBounds completes.
It's an old question, but it may be useful to others. I had the same problem, zoom_changed been triggered every time I called fitBounds() when adding several markers to a map. What I did was to add the listener to the map_changed event after the map was completely loaded, like this:
google.maps.event.addListener(map, 'tilesloaded', function() {
google.maps.event.addListener(map, 'zoom_changed', function() {
There is another way to do that by removing that that event. I think it would be much easier and cleaner than adding a global variable.
vm.map.events.bounds_changed = function() {
google.map.event.removeListener(zoom_changed);
}
Another way (forgotten to add that):
vm.map.events.bounds_changed = function() {
google.map.event.addEventListener(zoom_changed,function(mapper,eventName,args){});
}
In my app, I may fire off zoom change events programmatically, either via setZoom(), fitBounds(), or setOptions().
MAN = {};
MAN.globalMap = google.maps.Map(document.getElementById('map'));
I then route all programmatic calls to set the zoom through wrapper functions that flip a flag to false before they go on to set the zoom.
MAN.savedZoom = MAN.globalMap.getZoom();
MAN.saveZoomFlag = true;
// we want it to always be true, unless zoom was
// changed programatically.
MAN.setZoom = function setZoom(zoomLevel) {
console.log("won't save that I'm setting zoomLevel to " + zoomLevel);
this.saveZoomFlag = false;
MAN.globalMap.setZoom(zoomLevel);
};
MAN.fitBounds = function fitBounds(bounds) {
console.log("setting bounds, won't save zoomlevel.");
this.saveZoomFlag = false;
MAN.globalMap.fitBounds(bounds);
};
MAN.setOptions = function setOptions(options) {
console.log("setting options, won't save zoomlevel.");
this.saveZoomFlag = false;
MAN.globalMap.setOptions(options);
};
I then declare a listeners. At first I was declaring only the first, and was puzzled that it wasn't working:
google.maps.event.addListener(
MAN.globalMap,
'zoom_changed',
function zoom_changed_listener() {
console.log(
"zoom changed to " +
MAN.globalMap.getZoom() + "; " +
(MAN.saveZoomFlag ? "saving." : "not saving.")
);
if (MAN.saveZoomFlag) {
console.trace("saving");
MAN.savedZoom = MAN.globalMap.getZoom();
}
MAN.saveZoomFlag = true;
}
);
you may also find the idle event helpful, however, if you're just trying to avoid the initial set. See more about the maps events here: https://developers.google.com/maps/documentation/javascript/events
I suppose this should be simple. Have a variable say
var z = map.getZoom(); //scope this variable appropriately(somewhere before you call the fitbounds()
and then after the map.fitbounds() immediately do
map.setZoom(z); //this automatically changes the zoom level back to the previous level

Google Maps V3 - how to fire a callback function from gmap

I want to map a location, fill it's adress into an input field and add a marker.
Currently I have this, which works:
var home = new google.maps.LatLng(49.93547768118736, 11.2954580783844);
$('#map_canvas_1').gmap({'center': home, 'zoom':17 });
$('#map_canvas_1').gmap('addMarker', { 'position': home, 'animation' : google.maps.Animation.DROP } );
$('#map_canvas_1').gmap('search', { 'location': home }, function (results, status) {
$('#to').val(results[0].formatted_address);
});
What I'm wondering is why I cannot use a callback function to fill the input field like so:
$('#map_canvas_1').gmap({'center': home, 'zoom':17, 'callback': function() {
$('#map_canvas_1').gmap('search', { 'location': home }, function (results, status) {
$('#to').val(results[0].formatted_address);
});
} });
As a matter of fact, not even this works:
$('#map_canvas_1').gmap({'center': home, 'zoom':17, 'callback': function() {
alert ("callback");
} });
Can somebody tell me what I'm doing wrong?
There is no property 'callback' in MapOptions, so you cannot set it.
As I understood, you need a callback event, when the map is finally loaded. If I'm mistaken, please correct me. There is the "idle" event can be used to achieve it. I'm quite new with Google Maps and couldn't find another solution to fire a callback. If it helps, I will be glad. Sorry that the answer came for several years late, maybe other people will find it useful.
idle: function() {
alert('Done!');
}