Image causing click event to fire twice? - google-maps

I'm creating a Google map with markers and infowindows. I'd like each infowindow to have a zoom button that causes the Google map to zoom in and center and the corresponding marker.
See this jsfiddle for an example. The code for the infowindow is relatively simple:
infoWindowArray[i] = new google.maps.InfoWindow({
position: latlng,
content: "<a href='/"+pitches[i].slug+".html'>"+pitches[i].name + " ("+ pitches[i].club+")</a><br /><img width='16' alt='Loupe' src='//upload.wikimedia.org/wikipedia/commons/thumb/4/48/Loupe.svg/32px-Loupe.svg.png'/> <a id='zoom_"+pitches[i].id+"' href='javascript:void(0)'>Zoom In</a>"
});
However, my script is very temperamental in Chrome, and in Firefox it always fails. The reason is because one click is somehow being fired twice. So this function:
function setupZoomListeners(object, title, google_position, map){
google.maps.event.addListener(object, 'domready', function() {
google.maps.event.addDomListener(document.getElementById("zoom_"+title), 'click', function(){
if (document.getElementById("zoom_"+title).innerHTML == "Zoom In"){
map.setCenter(google_position);
map.setZoom(14);
document.getElementById("zoom_"+title).innerHTML = "Zoom out";
} else {
map.setCenter(new google.maps.LatLng(53.5, -2.2));
map.setZoom(6);
document.getElementById("zoom_"+title).innerHTML = "Zoom In";
}
});
}
is zooming in and out because it hears two clicks, so the net effect is nothing. However, simply removing the img tag in the infowindow appears to solve all.
Is there any earthly reason why the presence of an img tag would cause the script to interpret one click as two? I've seen lots of cases where too many clicks are registered - what generally causes this?
Can anyone advise how to solve this? Thanks.

Its capturing your domready event twice (at least in my version of firefox 19.0.2). You can see that if you start your zoomListeners function like so:
function setupZoomListeners(object, title, google_position, map){
console.log('zoomListener');
google.maps.event.addListener(object, 'domready', function() {
console.log('domReady');
google.maps.event.addDomListener(...
I don't think domready is a good event to be using here. Personally, I would just use one infoWindow object and populate with different HTML when the marker is clicked.
In any case, domready wasn't intended to be used for subsets of the dom as you are doing. I believe it's firing every time you change your markup. So when the lines starting document.getElementById("zoom_"+title).innerHTML = ... are executed the domready event will fire once again.

Related

Wrong code in tutorial for event listeners

I am following this tutorial to build a store locator page with a Mapbox map.
I don't want to add custom markers because I already have custom map labels (symbols?), which means I don't need the optional last section of the tutorial and stop right after Add Event Listeners.
Once this is completed, the page should react to clicks in the side panel list, as well as on the map (2 event listeners). However, in the demo provided in the tutorial for that particular step, you can tell the code for the second event listener, the one making the map clickable, is not functioning, which makes me believe there is a mistake in the provided code:
// Add an event listener for when a user clicks on the map
map.on('click', function(e) {
// Query all the rendered points in the view
var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
if (features.length) {
var clickedPoint = features[0];
// 1. Fly to the point
flyToStore(clickedPoint);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedPoint);
// 3. Highlight listing in sidebar (and remove highlight for all other listings)
var activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
var selectedFeature = clickedPoint.properties.address;
for (var i = 0; i < stores.features.length; i++) {
if (stores.features[i].properties.address === selectedFeature) {
selectedFeatureIndex = i;
}
}
// Select the correct list item using the found index and add the active class
var listing = document.getElementById('listing-' + selectedFeatureIndex);
listing.classList.add('active');
}
});
Would anyone be able to tell what is wrong with this code?
Turns out the code is incomplete in that the cursor doesn't change to a pointer as you hover over a map label/marker so it doesn't clue you into realising you can click on it, hence my assumption it wasn't working at all. I assume the general users who would then face the map would be equally deceived unless the pointer shows up. So in the tutorial, if you do go ahead and click the marker, it will have the expected behaviour and display the popup, although no pointer is shown.
Here is how to create the pointer, based on this fiddle: https://jsfiddle.net/Twalsh88/5j70wm8n/25/
map.on('mouseenter', 'locations', function(e) {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'locations', function() {
map.getCanvas().style.cursor = '';
});

GoogleMaps API V3 Polygon dblclick auto-complete

I have created a plotting system using the GoogleMaps Javascript API V3, which allows users to draw out and save polygons.
I have received a number of complaints concerning the autocompletion of plots as a result of accidentally doubleclicking while manually drawing out the points using the polygon drawing tool. I am therefore looking to disable this dblclick auto-complete function, so that plots will only complete once the user clicks on the first point again.
I have tried unbinding the dblclick event from the map, and attempted to stop propagation of the dblclick event by throwing an error on double click, as below (just to test the event call).
google.maps.event.addListener(map, 'dblclick', function(){
throw("stop");
});
this succeeds in stopping the zoom function on doubleclick, but autocomplete still occurs when dblclicking while plotting points (this listener is not triggered). I have even tried stopping the propagation of any doubleclick event on the whole page, all to no avail. Can anyone suggest either a way of unbinding this dblclick event, or an alternative solution to prevent the dblclick autocomplete?
I have searched through the API reference document and forums and have not been able to find a solution to this.
Add an edit button after finish!
Save your polygons into an array on "overlaycomplete" (and add your edit button at the same time)
var polyArray = [];
google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
this.setDrawingMode(null);
var shape = e.overlay;
shape.type = e.type;
polyArray.push(shape);
shape.addListener('click', function(evt){
if (evt.vertex != null && this.getPath().getLength() > 3) {
this.getPath().removeAt(evt.vertex);
}
});
});
The Edit function:
function editFeature(id, action){
var shape = polyArray[id];
if(action) shape.setEditable(true);
else shape.setEditable(false);
}

HTML5 Drag and Drop - Map

I have to make a map of Europe with its countries
and then I need a few pics of products from those countries
After that I have to match the pic with the country with drag and drop
if the product is dropped on the correct country it should send me to another page (with more info about the product)
if it's wrong it should display a message
anyone have an idea? I checked for some basic drag and drop stuff but since I'm new to html5 etc and webdesign in general it's really hard to make this from scratch
thanks!
EDIT: also only use HTML, CSS, JS
This can be achieved with the MapQuest JavaScript API. What I would start with is by adding polygon overlays to the map for each country, the colour can be sett to completely transparent by setting the opacity for the overlay to 0.0. From each overlay add a mouseup event listener to each overlay, this event listener can then be used to determine what it was you were dragging in the first place.
For the drag start functionality you can either do this yourself or you could use something like the jQuery UI draggable support, you could then use the dragstop event from the draggable API in conjunction with mouseup on the overlay to perform your logic.
Check out the basic map to get a map going.
Some code to start with
var countryCode;
// Adds an overlay and wires an event for mouseup.
function addMapOverlay(points, cc) {
var poly = new MQA.PolygonOverlay();
poly.setShapePoints(points);
poly.color = "#ffffff";
poly.colorAlpha=0.0;
poly.fillColor = "#ffffff";
poly.fillColorAlpha=0.0;
poly.addListener(rectangle, 'mouseup', function(evt) {
if (evt.eventName === "mouseup") {
// Here you have the event firing for the mouse-up on the overlay.
countryCode = cc;
}
});
}
For the drag-start.
$("#some-country-item").draggable({
start: function(event, ui) {
countryCode = null;
},
stop: function(event, ui) {
if (countryCode === "what you expected") {
// Released on correct country.
} else {
// Did not release on correct country.
}
}
});
You may need to test the event handling to ensure that the correct events are fired in the right order, or use the mouseover event on the overlay object.
The code samples are theoretical and should help you find the right direction to go.

Disable drag inertia / momentum on Google Maps V3

Is there a way to disable drag inertia on Google Maps V3? Seems like it should be a MapOption, but I can't find any way to do this.
I ran into this same problem today, with some custom Div's floating above the map needing to be re-positioned on Map Movement. My repositioning worked fine as long as the user came to a complete stop after dragging before letting the mouse go (so there would be no momentum), but if one just dragged quickly and released the div's would end up a bit off.
To fix this, I hooked into the drag event and the idle event:
var map = /* All the map config */
var stickyCenter = map.getCenter();
/* ... Code ... */
google.maps.event.addListener(map, 'drag', function(){ stickyCenter = map.getCenter(); });
google.maps.event.addListener(map, 'idle', function() { map.setCenter(stickyCenter); });
What happens is that after you've dragged and the map has come to a stop (after the momentum is done) the map 'snaps' back into place.
If the snapping is too sudden, one could probably panTo or animate the movement in some way. Hope that helps, it's not perfect, but it's a way to reverse the momentum from a drag event.
Use the undocumented option disablePanMomentum e.g.:
new google.maps.Map(document.getElementById(id), {
disablePanMomentum: true,
backgroundColor: 'none',
disableDefaultUI: true,
center: {
lat: 40.674,
lng: -73.945
},
zoom: 2,
...
This cannot be done with Maps API V3 at this time. Consider filing a feature request here:
http://code.google.com/p/gmaps-api-issues/
I'm pretty sure it's possible to at least counter-act the momentum. Somebody please correct me if I'm wrong! For the sake of simplicity, for instance, let's say your map container has a width of 100vw and a height of 100vh. You simply call getCenter() in a function that is called by a mouseup event, and then use those coordinates to immediately setCenter()?
function initMap(){
...
var win = window;
google.maps.event.addDomListener(win, 'mouseup', setCoords);
function setCoords(){
var x = myMap.getCenter();
var lat = x.lat();
var lng = x.lng();
myMap.addListener('center_changed', function(lat, lng){
myMap.setCenter(new google.maps.LatLng(lat, lng));
};
};
The code above actually works, but the kicker is that it only works once until the browser becomes seemingly overloaded and produces the error Uncaught RangeError: Maximum call stack size exceeded.
Not sure what to do now.
More info about this here.
This one works just fine for me:
map.addListener("dragend", () => map.setCenter(map.getCenter()));

Google Maps v3 InfoBox Add Event Listener

I have a Google Map (v3) with 20 markers. I have a single InfoBox instance that gets populated with a div that includes the text to fill the box as innerHTML.
I want to be able to click on the infobox and navigate away to a different page, but I can't get the infobox, or the div inside it to respond to a click event.
I've tried adding an event listener, and I've tried adding a domListener, but I can't get either to work.
Here are some snippets from my code
//setting up the infobox
var infobox = new InfoBox({
disableAutoPan: true
,isHidden:false
,pixelOffset: new google.maps.Size(-10, -10)
,closeBoxURL: ""
,pane: "mapPane"
,enableEventPropagation: true
});
//setting up the div
var boxText1 = document.createElement("div");
boxText1.id = "boxText1";
boxText1.className = "labelText";
boxText1.innerHTML = title1;//this is created earlier
//the marker event listener - the marker and coordinates are also set up earlier
google.maps.event.addListener(_marker1, 'click', function() {
infobox.content_ = boxText1;
infobox.position_ = mkLatLng1;
infobox.open(map);
});
//so far everything ok. When the user clicks the marker the infobox pops up - but.....
google.maps.event.addDomListener(boxText1,'click',function(){ alert('clicked!') });//doesn't work
I've tried a variety of other options, but they're all shots in the dark. What's the best way to listen for a click event on an infobox?
Thanks
Problem solved. In the infobox options you have to ensure that you have
pane: "floatPane"
and NOT
pane: "mapPane"
as I had it. Works fine now.
Interestingly the Google Docs say
Set the pane to "mapPane" if the InfoBox is being used as a map label.
What they don't say is that you can't use this option if you want the map label to be clickable.