I have a website at http://arquitectospelomundo.com which displays several markers, combined by the markerclusterer function, which display, when clicked, an infowindow with some info. When clicking directly on the map, the info window appears on the right spot; but when clicking on the sidebar (on one of the pictures), the info window goes out of bounds.
This was working correctly and suddenly changed; I am trying to figure it out but so far with no success. I would appreciate any help pointing me in the right direction.
Thank you.
As it seems the issue is related to the MarkerClusterer.
When the marker where the click has been triggered is inside a cluster the map-property of the marker is null and you get the wrong position.
Possible solution:
When the marker is within a cluster use a hidden marker(hidden via visible) as anchor for the infoWindow:
google.maps.event.addListener(marker, 'click', function() {
//create the dummy-marker on first click
if(!map.get('dummy')){
map.set('dummy',new google.maps.Marker({map:map,visible:false}))
}
var latLng = marker.getPosition();
//when the marker is within a cluster
if(!marker.getMap()){
//set position of the dummy
map.get('dummy').setPosition(latLng);
//use dummy as infowindow-anchor
marker= map.get('dummy');
}
map.panTo(latLng);
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
I had the same problem with Marker clusterer and outside clicks to the map, opening infowindows. The solution by #Dr.Molle with dummy markers is a nice direction, but the problem is that you can use the dummy to pan to, but the listener triggers a click on the marker which is not on the map. The correct infowindow opens, but the autopan feature has no way of knowing where to pan to, so it stays where it was after the last click. This is a problem with repeated clicks from outside the map. The first click goes okay, but the second or third one goes wrong, depening on if it was in a cluster or not.
The solution I found tests if the marker is in a cluster, if yes, attaches it to the map, and removes it after the click (not sure if that is neccessary, maybe to prevent the map from getting slow). I put it in the function that is called with each click from outside. But maybe you can also build it into the event listener. This works perfectly for me:
function openInfoWindow(id){
googlemap.setZoom(13);
var marker = markers[id];
var latLng = marker.getPosition();
if(!marker.getMap()){ //if the clicked marker is in a cluster, so it is not attached to a map
marker.setMap(googlemap); //attach it to the map
google.maps.event.trigger(marker, 'click'); // the standard trigger, opens infowindow
googlemap.panTo(latLng);
marker.setMap(null); //detach it from the map (not sure if necessary
} else {
google.maps.event.trigger(marker, 'click');
googlemap.panTo(latLng);
}
return false;
}
Related
I am working on a Google Map project. I need to accomplish something interactive. On the map, there will be lots of markers indicating different places and one place will be set as center. Clicking on the marker will pop up the infoWindow. On the infoWindow there will be a link named “NEXT”. Hitting that link will take the viewer to another marker place. It seems to be straight forward, so my question is there any API method to accomplish such task? Any help/suggestion will be highly appreciated.
Use the domready event of the infowindow to bind your click events, as described here.
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(infoWindow, 'domready', function() {
// whatever you want to do once the DOM is ready
});
I have a Google map that I am using to allow people to suggest locations. Currently I position a draggable marker in the centre of the map using a LatLng created with
myPosition = frmMap.getCenter();
What I would like to do though is place it initially somewhere to the edge of the map, perhaps directly under the zoom control (not unlike the way you see the yellow street view man above the zoom control).
I've searched for a solution but am not coming up with anything. My only idea was to do some maths based on the Center and NortEast but I'd rather have an absolute position based on pixels if that's possible?
As I mentioned in the comments, computing a latlng value for a marker to position under the zoom controls is not only cumbersome, but might not be feasible if the user starts panning/zooming around in the map (as the marker will move wherever the latlng takes it).
My suggestion would be to use the Drawing Library provided by the Maps API. This basically gives you a drawing control, to add markers to the map (other overlays are possible too: cirlce, polygon, polyline, rectangle). And like any control google maps provides, you can strictly position them anywhere you'd like - by setting it in the options. The snippet below describes how you initialize the drawing library:
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControlOptions: {
position: google.maps.ControlPosition.LEFT_BOTTOM,
drawingModes: [
google.maps.drawing.OverlayType.MARKER
]
}
});
drawingManager.setMap(map);
This gives you your drawing control, with the mode for Marker enabled, and binds it to your map object.
You can then listen to when a marker's been added by adding a listener on the drawingManager variable for the markercomplete event. Then in the call back you can get the position of the added marker, the snippet below demonstrates this:
google.maps.event.addListener(drawingManager, 'markercomplete', function (marker) {
var position = marker.getPosition();
});
I put together a small jsfiddle with this example if you'd like to see it in action. Also, click here for full reference of the Drawing Library for the maps api.
EDIT: (start mode in marker add on map load, hide drawing controls after marker added, maker marker draggable)
To start the drawing mode to add marker on map load, simply set the drawingMode option in your drawingManager variable declaration:
`drawingMode : google.maps.drawing.OverlayType.MARKER`
You can hide the drawing controls in the markercomplete event listener:
// To hide:
drawingManager.setOptions({
drawingControl: false //changes UI back to regular map interactions
});
drawingManager.setDrawingMode(null); //hides controls
Alternatively, if you're never going to need the drawing controls again later in your client interactions you can remove it from the map complete via:
drawingManager.setMap(null);
Then to make the marker draggable, just set the option in the listener as well (because the marker in the callback function is a google maps marker object anyway - which references the marker that's added to your map).
marker.setOptions({
draggable: true
});
You can then add a listener on the marker object for the dragend event to track changes to the location.
Here's in updated fiddle: http://jsfiddle.net/svigna/J5zMg/3/
I'm creating a map that loads & destroys markers based on both the bounding box and zoom level. I'm having a real problem getting markers to properly be removed, it seems to work sometimes for certain situations.
I have an object that contains the marker info, which also contains the google maps marker object. My code detects if the market should be deleted based on the bounding box or zoom-level. I set the marker object to "setMap(null);" and using firebug I can see that its being set, I then remove the parent object entirely and the objects data length is updated properly.
I output to the firebug console when a marker is supposedly deleted, seems to be working and I can see that the marker isn't being re-crated from the ajax call for markers on the boundingbox change.
Yet if I zoom around the map I can sometimes see that the markers are being removed, if I zoom away then pan back holding the mouse down. Or sometimes the markers will all be removed if I zoomout the first time, but if I zoom in again then back out they are not removed.
I must be doing something wrong with the logic of my code, I'm stumped.
You can view the source of
http://www.trailforks.com/map/test.php?lat=49.352247&lon=-123.202413
the JS is
http://www.trailforks.com/map/includes/map.js
the code for deleting a marker is at the bottom
function clearMarkerMemory(mapItem, i) {
google.maps.event.removeListener(mapItem.lis); // remove stored listener
mapper.data[i].obj.setMap(null); // remove marker
mapper.data.splice(i, 1);
console.log("removed marker "+mapItem.icon+":"+mapItem.nid+' '+mapItem.name);
};
I added some more debug into to the console, going to a simple area of the map with only 2 markers http://www.trailforks.com/map/test.php?lat=49.43210641783767&lon=-123.49878636730955&z=14
I can see the markers created, then move the map a bit and see that the markers weren't re-created because they were detected in the marker object. I then move the viewport so one of the markers is off the screen and I can see that the marker is removed and the marker object length updates. But if I pan the map back over the marker is still on the map.
I was struggling with similar problem for a long while until I realized that the map marker's setMap-method is asynchronous. When you call that and immediately remove any references to that marker object, the browser's garbage collector steps in and cleans it up from the memory and thus prevents the actual remove operation from happening.
Try it out by just commenting out the line with the splice call and see if that helps. If it does help, you should consider delaying the removal of the object, or alternatively storing the reference to the marker object until it's really removed. How to detect if it's really removed? I have no idea.
I hope this helps!
Instead of doing:
google.maps.event.addListener(map, 'dragend', function() { refreshMarkers(); }); //refresh markers when user moves map
google.maps.event.addListener(map, 'zoom_changed', function() { refreshMarkers(); }); //refresh markers when user moves map
change it to:
EDIT, (after comments):
To prevent multiple instances of the event handler occurring simultaneously, a global variable could be used, as follows:
google.maps.event.addListener(map, 'bounds_changed', function() {
if (processing) { // var processing is global
return;
}
processing = true;
refreshMarkers();
processing = false;
}); //refresh markers when user moves map
That should cover both situations. As it is now, with two different event listeners, the AJAX calls could be conflicting, and you maybe firing a second call before the first one has completed.
I have many map markers with the exact same lat/long cords so no matter how far in I zoom my map still shows the marker cluster and the number of results.
Is there a way to have some onclick or onhover event so that it shows an info box with all of the markers in that cluster in a list? Then clicking a link within that info box opens up that individual marker info box?
I've read solutions to change the lat, long by a small amount so that they aren't the same location. I think that is very messy and not that good anyways if there ends up being multiple markers 10+ anyways at the same locationg. I think it'd be much easier for a user to just click the cluster and bring up the info window with all of those markers in there with links.
Or if someone knows another plugin that does what I am seeking I could work with that too. I just haven't found much info on it.
There might be a plug in out there to do what you want, but it's also possible to do without one. I did something like that in one of my projects.
Add event listener to each marker; clicking opens marker list info window
The content of the marker list info window contains onclick attributes that will open the marker info window.
My code was tucked away into functions, but it was basically just this:
//1) while creating marker, create click listener that opens the marker list
google.maps.event.addListener(marker, 'click', function() {
markerWindow.close();
markerList.open(map, marker);
});
//2) store the content required by the marker's info windows
var markers = [
[marker1Reference, "The Stadium"],
[maerker2Reference, "The Supermarket"]
];
//3) the function that is called each time a marker is chosen from the marker list
function openMarkerInfo(markerIndex) {
markerList.close();
markerWindow.setContent(markers[markerIndex][1]);
markerWindow.open(map, markers[markerIndex][0]);
}
//4) info window for the marker list - the content includes JS onclick events that will open each marker info window
markerList = new google.maps.InfoWindow({
content: "Choose:<br><br><div href='' class='markerLink' onclick='openMarkerInfo(0)'>The Stadium</div><br><div href='' class='markerLink' onclick='openMarkerInfo(1)'>My House</div>"
});
//5) the marker window that will get set each time a marker is clicked in the list
markerWindow = new google.maps.InfoWindow();
Hope that helps!
I see that there is a getVisible call, but that only checks if the marker is on the map NOT if the marker is in the current view.
I want to check if the marker is in the current view bounds?
I guess you want
map.getBounds().contains(marker.getPosition())
You need to tell map that your markers should be contained within view by adding following code
google.maps.event.addListener(map, 'bounds_changed', function() {
map.getBounds().contains(marker.getPosition())
});
Here bound_changed event is triggered.