javascript google maps api remove markers - javascript

I have functions that when a li element is clicked markers are added to the map. If another li is clicked then the original markers are removed and the new one appearr.
The issue I am having is that the markers are placed on the map when a li is clicked for the first time. When a second li is clicked the markers are removed but the new ones are not added. I get no error in firebug. I cant see what I am missing.
$(document).ready(function() {
$(".markerSelection").click(function() {
var selectionId = $(this).attr("id");
drop(selectionId);
});
});
var markers = {
shopping : [
new google.maps.LatLng(52.26183, -7.11339),
new google.maps.LatLng(52.26134, -7.11226),
new google.maps.LatLng(52.26067, -7.11181),
new google.maps.LatLng(52.26003, -7.11033)],
cars : [
new google.maps.LatLng(52.26183, -7.11339),
new google.maps.LatLng(52.26134, -7.11226),
new google.maps.LatLng(52.26067, -7.11181),
new google.maps.LatLng(52.26003, -7.11033)]
};
var iterator = 0;
function drop(selectionId) {
clearOverlays();
for (var i = 0; i < markers[selectionId].length; i++) {
setTimeout(function() {
addMarker(selectionId);
}, i * 200);
}
}
function addMarker(selectionId) {
marker = new google.maps.Marker({
position: markers[selectionId][iterator],
map: map,
draggable: false,
animation: google.maps.Animation.DROP
});
iterator++;
markersArray.push(marker);
}
// Removes the overlays from the map, but keeps them in the array
function clearOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
}
}

I reviewed your code one more time, and I think the problem is with iterator, which is initialized to 0 in global scope. That is why the first time it works okay, but after that, indices exceed. It seems you should set it to zero at the beginning of the drop() function.
However it makes more sense if you pass index as a second parameter of addMarker() instead of an outer variable which is handled in drop() and complicate you code.

You have defined markers as a Json variable, but I don't know what you mean by markers[selectionId]! Markers is not defined as an array and it seems it's not correct to refer to it by index!

Related

how to remove map markers on setInterval refresh (js)

Guys need a bit of help with google maps, I'm creating a tracking web app using MySQL DB coordinates, the tracking works well so far except the google map markers keep repeating when refreshed, I have set the map marker refresh using a setInterval function for every 5 seconds(for testing). I've tried clearoverlays() methods and remove map markers method(from google sample) but doesn't work. Appreciate your help, thank you
<script defer
src="https://maps.googleapis.com/maps/api/js?key="KEY"8&callback=initMap">
</script>
<script type="text/javascript">
setInterval(function () {
BindMarker();
}, 5000);
var customIcons = {
blue: { icon: 'blue48.png'},
};
var marker;
var map = null;
var infoWindow = null;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(1.4370993, 110.3387572),
zoom:15,
});
infoWindow = new google.maps.InfoWindow;
}
function BindMarker() {
downloadUrl('maps1.php', function (data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var icon = customIcons["blue"] || {};
marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.BOUNCE,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
}
});
}
function bindInfoWindow(marker, map, infoWindow) {
google.maps.event.addListener(marker, 'click', function () {
map.setCenter(marker.getPosition());
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function () {
if (request.readyState == 4) {
request.önreadystatechange = doNothing;
callback(request, request.status); }
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() { }
</script>
The functions I tried are given below( I called the remove overlays function, remove markers and also the delete markers function before BindMarker() inside the setInterval function so that it would remove the markers before binding new markers
function setMapOnAll(map) {
for (let i = 0; i < markers.length; i++) { markers[i].setMap(map); }
}
function clearMarkers() {setMapOnAll(null); }
function deleteMarkers() {clearMarkers(); markers = [];}
function clearOverlays() {
while(markers.length) { markers.pop().setMap(null); }
markers.length = 0;
}
I believe you've confounded the examples, which your attempted code shows verbatim and what your code is actually doing.
It the sample code you're drawing from, the variable markers is an array of Google Map marker objects. So this code makes sense in that regard:
function deleteMarkers() {clearMarkers(); markers = [];}
But, your code is not creating an array of those objects. Your code does not have a variable named markers that is accessible outside of the downloadUrl() function. The variable markers does show up inside that function, but it contains an HTMLCollection element - not an array of markers.
To fix this you need to create an array named markers right after the variable name marker is created.
Then, within the for loop, just after you create the marker push that marker on to the markers array. You will also have to rename the existing markers variable to something more appropriate like markerElements.
Now, the deleteMarkers() function will work as expected.

I want to insert the model[i].marker.addListener function outside the loop

function pushMarkers() {
locInfo = new google.maps.InfoWindow();
for (var i = 0; i < model.length; i++) {
var loc = model[i].places;
var title = model[i].title;
model[i].marker = new google.maps.Marker({
position: loc,
title: title,
animation: google.maps.Animation.DROP,
map: map,
id: i
});
console.log(model[i].title);
model[i].marker.addListener('click', function() {
console.log('InfoWindow Loop entered');
toggleBounce(this);
populateInfoWindow(this, locInfo);
});
wikiLink(model[i].marker);
}
}
Its not advisable to make functions within a loop so i want to make the function outside the loop.
You shouldn't make multiple functions at all, in point of fact, you should just make it once and then attach it as a listener in the loop. such that:
function handleMarkerClick() {
console.log('InfoWindow Loop entered');
toggleBounce(this);
populateInfoWindow(this, locInfo);
}
model[i].marker.addEventListener('click', handleMarkerClick);
Note that if you need to pass contextual information to that handleMarkerClick function that's only available inside the loop, let's say you want it to know the index (i) for some reason, you can bind it:
model[i].marker.addEventListener('click', handleMarkerClick.bind(model[i].marker, i);
and then the signature of the function would need to be function handleMarkerClick(i, event){}

google maps click event not working completely correct

I use the following script to generate this page
function initialize() {
var mapCanvas = document.getElementById('map');
var mapOptions = {center:new google.maps.LatLng(latitudeMid,longitudeMid),zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,streetViewControl:false,mapTypeControl:true,scaleControl:true,scaleControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT}};
var map = new google.maps.Map(mapCanvas, mapOptions);
var i;
var insertion;
var previousMarker;
// -------------------------------
//show locations on the map
// -------------------------------
for (i = 0; i < fotoCount; i++) {
var myLatLng=new google.maps.LatLng(Latituden[i], Longituden[i]);
var marker = new StyledMarker({styleIcon:new StyledIcon(StyledIconTypes.MARKER,{color:'00ff00',text:Letters[i]}),position:myLatLng,map:map});
marker.set('zIndex', -i);
insertion='<img src=\"http://www.pdavis.nl/Ams/'.concat(Bestanden[i],'.jpg\"></img>');
insertion=insertion.concat('<table class=width100><tr><td>Bestand: ',Bestanden[i],'</td><td class=pright>Lokatie: ',Latituden[i],' °N., ',Longituden[i],' °E. (',Letters[i],')</td>');
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[i],'</td></tr><td colspan=3>Object: ',Objecten[i],'</td></table>');
google.maps.event.addListener(marker, 'click', function() {
$('#photo').html(insertion);
this.styleIcon.set('color', 'ff0000');
if(previousMarker!=null){previousMarker.styleIcon.set('color', '00ff00')};
previousMarker=this;
});
}
Clicking a marker should do two things: (i) turn the marker red (and any existing red marker green) and (ii) show the appropriate photo with information in the right-hand panel. The first does work, but the second always shows the photo corresponding to the last marker. Using
"alert(insertion);" shows that this is correct for each marker.
You can't do it this way because at the end of the loop, "i" will always be the last index. And of course when you click on a marker, "i" value inside the callback is the last index, so you should always have the last picture displayed.
Just put insertion code inside your click callback isn't enough because of the i value. You didn't bind anything to fix value in your callback so you will have the same problem.
The following solution use the marker object to bind the "i" value, like this you can use it in your callback.
Script tested on your page :).
Adapt it as you want !
function initialize() {
var mapCanvas = document.getElementById('map');
var mapOptions = {center:new google.maps.LatLng(latitudeMid,longitudeMid),zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,streetViewControl:false,mapTypeControl:true,scaleControl:true,scaleControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT}};
var map = new google.maps.Map(mapCanvas, mapOptions);
var i;
var previousMarker;
// -------------------------------
//show locations on the map
// -------------------------------
for (i = 0; i < fotoCount; i++) {
var myLatLng=new google.maps.LatLng(Latituden[i], Longituden[i]);
var marker = new StyledMarker({styleIcon:new StyledIcon(StyledIconTypes.MARKER,{color:'00ff00',text:Letters[i]}),position:myLatLng,map:map});
marker.set('zIndex', -i);
marker.myIndex = i;
google.maps.event.addListener(marker, 'click', function() {
var insertion = "";
insertion='<img src=\"http://www.pdavis.nl/Ams/'.concat(Bestanden[this.myIndex],'.jpg\"></img>');
insertion=insertion.concat('<table class=width100><tr><td>Bestand: ',Bestanden[this.myIndex],'</td><td class=pright>Lokatie: ',Latituden[this.myIndex],' °N., ',Longituden[this.myIndex],' °E. (',Letters[this.myIndex],')</td>');
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[this.myIndex],'</td></tr><td colspan=3>Object: ',Objecten[this.myIndex],'</td></table>');
$('#photo').html(insertion);
this.styleIcon.set('color', 'ff0000');
if(previousMarker!=null){previousMarker.styleIcon.set('color', '00ff00')};
previousMarker=this;
});
}
}
insertion should be an array. This way when you iterate, in eacj iteration you are just overwriting the content of insertion. In the end you have last value from image array as insertion.
var insertionArr = [];
...
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[i],'</td></tr><td colspan=3>Object: ',Objecten[i],'</td></table>');
insertionArr[marker] = insertion; // Add it to the array
google.maps.event.addListener(marker, 'click', function() {
$('#photo').html(insertionArr[this]);// get it from the array
...
});
This is not tested code.

Place multiple markers on google map with callback function

I want to implement a functionality on Gmap API, that if the zoom is more than 17, show all the markers(otherwise, just hide them). However, when I write code like the following, it just does not work.
PS: the code might not be exactly correct in syntax and arrangement, but it express what I mean
// #latlong is an array of tuple (latitude , longtitude)
// #myMap is the google map object passed to the function
function placeMarker( myMap , latlon)
{
for(var i = 0 ; i < latlon.length ; i ++)
{
myMarker = new google.maps.Marker( {
position: new google.maps.LatLng(latlon[i][0], latlon[i][1])
});
google.maps.event.addListener(myMap, 'zoom_changed', function() {
zoomLevel = myMap.getZoom()
if(zoomLevel >= 17)
{
myMarker.setMap(myMap)
}
else
{
myMarker.setMap(null)
}
});
}
}
And I just change my code to:
function placeMarker( myMap , latlon)
{
for(var i = 0 ; i < latlon.length ; i ++)
{
myMarker = new google.maps.Marker( {
position: new google.maps.LatLng(latlon[i][0], latlon[i][1])
});
(function(myMarker_copy){
google.maps.event.addListener(myMap, 'zoom_changed', function() {
zoomLevel = myMap.getZoom()
if(zoomLevel >= 17)
{
myMarker_copy.setMap(myMap)
}
else
{
myMarker_copy.setMap(null)
}
});
}(myMarker));
}
}
And the second version works.
I know how to make it work, however, I really do not know why it work and why the other does not. Maybe this has something to do with the function closure or parameter passing principle of JS(I have checked a lot references, but some of them just hold different ideas). Could anybody give me a help?
really appreciate it.
The first example which doesn't work: There is one global variable myMarker and many event listeners which at the end all operate on one marker and that is the one created the last in the loop.
The second example which does work: because of closure each event listener receive its own local copy of marker variable. So, when event listener is called it has correct marker value.

javascript variables and asynchronous calls

I have the following code, and having read this, i understand it wont work because the getJSON call is asynchronous. How do i need to change this so that the MarkerClusterer function gets triggered with a full set of markers? I've tried putting the MarkerClusterer function inside the getJSON call but with no luck...
var mcOptions = {gridSize: 50, maxZoom: 9};
var markers = [];
function parse_json(json) {
if (json.length > 0) {
for (i=0; i<json.length; i++) {
var report = json[i];
var latLng = new google.maps.LatLng(report.latitude, report.longitude);
markers[i] = new google.maps.Marker({
position: latLng,
title: report.name + ' ' + report.surf_size_ft_round,
url: "/place/"+report.slug
});
google.maps.event.addListener(markers[i], 'click', function() {
window.location.href = markers[i].url;
});
markers.push(markers[i]);
}
}
};
$.getJSON('<%= request.fullpath + ".json" %>', function(stream) {
if (stream.length > 0) {
parse_json(stream);
alert(markers[1].title); //sanity check - gives result
}
});
alert(markers[5].title); // sanity check - empty
var mc = new MarkerClusterer(map, markers, mcOptions);
Why not put this code snippet:
mc = new MarkerClusterer(map, markers, mcOptions);
inside the anonymous callback function in your $.getJSON? Just declare var mc; somewhere outside the $.getJSON scope to be able to have access to it elsewhere.
Alternatively, you can fire an event at the end of your parse_json function, listen to that event and then fire up another function that creates your MarkerClusterer object when the event has fired. Check this out: How to trigger event in JavaScript?
EDIT:
Upon inspecting your code a bit more, I can see that you set markers[i] to a new Marker instance and then push onto the markers array that same instance. You probably want to either set markers[i] to a new Marker instance or you want to create a var marker, setting it to a new Marker instance and then pushing on the markers array.
Maybe you need to put it inside the success function you give as an input to $.getJSON?
$.getJSON('<%= request.fullpath + ".json" %>', function(stream) {
if (stream.length > 0) {
parse_json(stream);
alert(markers[1].title); //sanity check - gives result
mc = new MarkerClusterer(map, markers, mcOptions);
}
});
alert(markers[5].title); // sanity check - empty

Categories