Add multiple markers with Google Maps API v3 - javascript

I have the following function to add one single marker but I want to add multiple markers by clicking on the map. I have Googled but I can't get any straight answer on how I can solve this problem.
function placeMarker(location) {
if(marker) {
marker.setPosition(location);
} else {
marker = new google.maps.Marker({
position: location,
map: gm_map,
draggable: true
});
}
}
I know I need to use Array() but I don't know exactly how. How can I solve my problem?
DEMO: removed because the problem has been solved.

Do you need to use the marker variable outside of the placeMarker function? Your function is not deleting the marker, it is checking to see if the marker variable exists and moves the marker using the setPosition function. You need to remove that line if you want multiple markers to exist.
function placeMarker(location) {
//marker variable will only exist inside this function
var marker = new google.maps.Marker({
position: location,
map: gm_map,
draggable: true
});
}
Here is an example: http://jsfiddle.net/bryan_weaver/aEyfW/

Ok, you need to have an event listener for the 'click' event on the map. And this needs to pass the currently-clicked location to your placeMarker function. Try this (add this event listener in the same place where you initialise your map)
google.maps.event.addListener(gm_map, 'click', function(event) {
placeMarker(event.latLng);
});
And modify your placeMarker function, so instead of having one global variable marker which you update with each click, create a new marker each time:
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: gm_map,
draggable: true
});
}

Related

Google Maps Marker On Load Handler?

All,
Very simply - is there an onload handler / event for when all markers have loaded?
Eg we have 26 markers being loaded, and this is loading well before the markers:
google.maps.event.addListenerOnce(map, 'idle', function(){
// do something only the first time the map is loaded
});
Also fyi this does not work:
google.maps.event.addListenerOnce(marker,'load',function(){
// onload stuff
});
Thoughts?
Team,
Ok so I think I answered my own question - Not as elegant as I'd hoped but this works:
In our createMarker function, I added a 'checkloaded()' bit to the end, which checks if locations.length = markers.length:
function createMarker(add,lat,lng,marker_label) {
var contentString = '<div contentEditable="true">'+marker_label+'</div>';
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat,lng),
map: map,
draggable: true,
label: labels[labelIndex++ % labels.length]
});
// open marker on load
google.maps.event.trigger(marker,'click');
bounds.extend(marker.position);
//Add marker to the array.
markers.push(marker);
checkloaded();
}
And then:
function checkloaded(){
if(locations.length == markers.length){
// do onload stuff here
}
}
If there is a proper way to do that, let me know and thank you all

Google maps - reuse single infoWindow for multiple markers

I have multiple markers and currently when more than one infoWindow is clicked, the other already-opened infoWindows stay open, cluttering the map. I would prefer it if I could simply reuse a single infoWindow, move it and update it's content. This is what I am attempting to do below:
var info = new SnazzyInfoWindow ();
/*
* Loop through each item in the 'features' array, including info windows, and display the marker
*/
features.forEach(function (feature) {
var marker = new google.maps.Marker({
position: feature.position,
icon: icons[feature.type].icon,
map: map
});
var infoContent = feature.contentImage + feature.content;
marker.addListener('click', function() {
infoCallback(infoContent, marker);
});
});
function infoCallback(infoContent, marker) {
return function() {
info.close();
info.setContent(infoContent)
info.open(map, marker);
};
};
However I am receiving the error Cannot read property 'placement' of undefined and can't seem to figure out what's wrong here.
Note that I am using the "Snazzy Info Window" plugin, but I think the same would apply to the stock infoWindow.
Yes. Inside the onClick function, when marker.addListener('click' is being executed, you don't have feature/marker. The variables are not what they were when the foreach was executed.
One trick I mostly use, is to make an array of the marker objects. Inside the onClick you search for the 'this' marker inside the array.
Something like this:
var markers = []; // store the markers in this array
features.forEach(function (feature) {
var marker = new google.maps.Marker({
position: feature.position,
icon: icons[feature.type].icon,
map: map
});
markers.push(marker);
marker.addListener('click', function() {
// first find out which marker was clicked on
var index = markers.indexOf(this); // this represents the marker that was clicked on
// index should be the same index as the index for features.
var feature = features[index];
var marker = markers[index];
var infoContent = feature.contentImage + feature.content;
// now we can call infoCallback.
infoCallback(infoContent, marker);
});
});

google maps multiple markers clickevent

Im looping and placing some markers, but when i click a marker, they all respond with the same value
Here is my code
for(a=0; a < prod.length; a++){
// we add marker to map
var myLatlng = new google.maps.LatLng(prod[a]['lat'],prod[a]['lon']);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: prod[a]['name']+" \n"+prod[a]['description'],
icon: image
});
google.maps.event.addListener(marker, "click", function() {
show_details(a);
});
}
function show_details, a always has the same value
I have looked at the other answers here but that didnt solve my problem.
Tipical problem in async programming/scripting. The a variable passing, when the click event runs, so , the value of that is what is after the for loop finishes.
You should create an inner function scope, and save the value of a in a variable, what lives only in that scope.
The solution:
(function(z){
google.maps.event.addListener(marker, "click", function() {
show_details(z);
});
})(a);
The a variable lives outside the callback function too. So if you modify the value of a ( or the for loop modify that) and when the event handler is called, it see the modified a.
Help link: http://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/ .

Adding Event Listener causes Google Map to freeze

I am attempting to create a google map with markers on my page. I have an unordered list where each item has data attributes for latitude, longitude and title. Using JQuery I pull these values and produce a marker on the map for each item in the list. Everything seems to work OK except google maps will not load tiles as you pan around the map.
This is how I initialize the map:
var map;
// initialize google map
$(function () {
var myOptions = {
zoom: 10,
center: new google.maps.LatLng(CoordinatesLat, CoordinatesLong),
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
}
// initiate map
map = new google.maps.Map($("#map")[0], myOptions);
// when map is loaded, add events and behaviors to it
google.maps.event.addListenerOnce(map, 'tilesloaded', addEventsToMap(".event")); //commenting this line prevents GMAP problems
});
FYI - before I was using maps.event.addListener() and the map would work momentarily and then become completely unresponsive. Changing it to maps.event.addListenerOnce() stopped the freezing but still has the tile loading problem.
And this is the callback, where evidently I've done something wrong:
//add events from event list to map. add behavior to events ie. mouseover
function addEventsToMap(selector) {
$(selector).each(function (i, $e) {
$e = $($e);
var latlng;
if ($e.attr("data-geo-lat") && $e.attr("data-geo-long")) {
latlng = new google.maps.LatLng($e.attr("data-geo-lat"), $e.attr("data-geo-long"));
$e.marker = new google.maps.Marker({
position: latlng,
map: map,
title: $e.attr("data-title")
});
google.maps.event.addListener($e.marker, 'click', function () { window.location = $e.attr("data-href"); });
google.maps.event.addListener($e.marker, 'mouseover', function () { $e.addClass("event-hover"); });
google.maps.event.addListener($e.marker, 'mouseout', function () { $e.removeClass("event-hover"); });
//when mouse hovers over item in list, center map on it's marker
$e.mouseenter(function () {
map.panTo(latlng);
});
}
});
}
Any idea what could be causing this?
I see a problem, though I'm not sure if it's the issue here. If you examine this line:
google.maps.event.addListenerOnce(map, 'tilesloaded', addEventsToMap(".event"));
What you are intending to do is call your 'addEventsToMap' once the map is loaded, but instead what you are doing is calling the function and then assigning the return value of that as a listener.
You need this instead, and I think it shouldn't crash anymore.
google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
addEventsToMap(".event");
});
If that doesn't work, I would recommend looking at the Javascript Console of whatever browser you are using, to see what error is happening to make the map crash.

Setting infoWindow for a list of markers created inside a callback function (directionsService)

I'm trying to set infoWindows for markers that are created in the callback function of a directionsService (Google Maps API V3). I tried many different ways to do that without any luck..
Here is a skeleton of how my code looks like:
for(i=0;i<markersList.length;i++){
map = someMap
var request = myRequestObject;
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
directionsService.route(request, (function (address) {
return function(response, status) {
//Use the directions service to do some stuff
//..Then create markers
var marker = new google.maps.Marker({
map: map,
title: address['title']
});
//push the marker to a list of markers attached to the map
//this can be useful to delete all markers in a later step
map.markers.push(marker);
//Creating multiple instances of infoWindows works fine though..
//However, Creating 1 info window for the whole map doesn't work from here
//If I try that, I'd set the same content for all info windows
//which is not what I want.
}
}
)(markersList[i])
);
}
I tried doing this, which didn't work either:
//add setInfo as a custom function to my map
//then call it to iterate over all markers and add info windows
google.maps.Map.prototype.setInfo = function() {
for(var i=0; i < this.markers.length; i++){
infowindow.setContent(this.markers[i].getTitle());
google.maps.event.addListener(this.markers[i], 'click', function(){
infowindow.close();
infowindow.open(map,this.markers[i]);
});
}
};
Then I'd call this function after I'm done with directionsService.route (check the first code block), outside my main for-loop. However, it never finds any markers attached to the map for some reason..
Any thoughts on how to assign the right infoWindows to the map markers?
I want to have 1 infoWindow instance so that I could close it when a new infoWindow is clicked (infoWindow.close()).
Thanks!
Here is how I do it within a geocoder callback function (a little different than the directionService, but still using a callback function, so the methodology should be the same) using only one infowindow. I would use this in a loop when geocoding a bunch of addresses.
var infowindow = new google.maps.InfoWindow();
geocoder.geocode( { 'address': value}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//create and add marker to map based off geocode result
var marker = new google.maps.Marker({
map: map,
title: results[0].formatted_address,
position: results[0].geometry.location
});
//add marker to array so we can clear it later
markersArray.push(marker);
//create listener for marker infowindow and set content
google.maps.event.addListener(marker, 'click', function() {
infowindow.close();
infowindow.setContent(results[0].formatted_address);
infowindow.open(map,marker);
});
}
});
One way to do this is have an external function that sets the content on the infowindow, and as you add your markers, you call that function instead of having the event listener declared inline within your loop. The problem is that after all the markers are created, when you click one, it will just use whatever the value of results[0].formatted_address is, which is whatever it was last set to at the end of the loop.
var marker = new google.maps.Marker({
map: map,
title: address['title']
});
//push the marker to a list of markers attached to the map
//this can be useful to delete all markers in a later step
map.markers.push(marker);
// add an event listener for this marker
bindInfoWindow(marker, map, infowindow, address['title']);
And that function is simply:
function bindInfoWindow(marker, map, infowindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(html);
infowindow.open(map, marker);
});
}
PS: You shouldn't need to call infowindow.close() prior to calling infowindow.open(). As there's only one infowindow, the API will automatically close it before reopening it at the new location.

Categories

Resources