Google Maps marker has to be clicked twice to register - javascript

Sometimes, when I click on a marker once, all of the markers disappear for a second and reappear. Then I have to click again on a marker for the click event to register and the Info-Box to display. I am pretty sure this is also the reason why my markers don't disappear when I call the clearMarkers() function if I haven't already clicked on a marker. Here is my code:
var map;
var markersArray = [];
var cat = "restaurants, All";
var C = [...];
var D = [...];
function initMap() {
// Create a map object and specify the Div element to display it on
loc = {lat: 41.902783, lng: 12.496366};
map = new google.maps.Map(document.getElementById('map'), {
center: loc,
zoom: 14,
disableDefaultUI: true
});
// Displays all of the markers when page loads, all restaurants
getJsonData('yelpdata.php?cat=restaurants, All&lat='+loc.lat+'&lng='+loc.lng, map);
var filtersPanel = document.getElementById('filtersPanel');
var textField1 = document.getElementById('userInput');
// Displays the markers according the value the user is typing (cat)
function useValue() {
clearMarkers();
var textFieldVal = textField1.value;
var ind = findIndex(textFieldVal);
if (ind != -1) {
cat = D[ind];
}
getJsonData('yelpdata.php?cat='+cat+'&lat='+loc.lat+'&lng='+loc.lng, map);
}
// Text box event handlers
//textField1.oninput = useValue;
textField1.onchange = useValue;
textField1.addEventListener("awesomplete-selectcomplete", useValue);
google.maps.event.addListener(map, 'click', function(event) {
latitude = event.latLng.lat();
longitude = event.latLng.lng();
newCenter = {lat: latitude, lng: longitude};
map.setCenter(newCenter);
loc = newCenter;
useValue();
});
var autocomplete = new Awesomplete(textField1, {
list: C,
filter: Awesomplete.FILTER_STARTSWITH,
minChars: 1,
autoFirst: true
});
// Displays the filters panel in the top-left of the screen
map.controls[google.maps.ControlPosition.TOP_LEFT].push(filtersPanel);
}
function findIndex(cat) {
for(var i=0; i<C.length; i++) {
if(C[i] == cat)
return i;
}
return -1;
}
function clearMarkers() {
// Clears the markers from the map and array
for (var i=0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
markersArray = [];
}
function getJsonData(url, map) {
// Using AJAX to get the JSON data from the 'yelpdata.php' file and display markers with info-boxes on the map
var request = new XMLHttpRequest; // the main object to request the XML
request.onreadystatechange = function() { // when the request changes state
if (request.readyState == 4) { // success, we have recieved the XML object from sending the request
var json = request.responseText;
var obj = JSON.parse(json);
var numMarkers = obj.businesses.length;
document.getElementById("numResults").innerHTML = numMarkers + " results";
for (var i = 0; i < obj.businesses.length; i++) {
(function(index) {
// Getting all of the attributes for each business from the JSON
var business = obj.businesses[index];
var name = business.name;
var catArr = business.categories;
var catStr = "";
for (j=0; j < catArr.length; j++) {
if (j == 0) {
catStr += catArr[j].title;
} else if (j > 0) {
catStr += ", " + catArr[j].title;
}
}
var reviews = business.review_count;
var rating = business.rating;
var address = business.location.address1 + ", " + business.location.city + ", " + business.location.state;
var coord = {lat: business.coordinates.latitude,
lng: business.coordinates.longitude};
var url = business.url;
var img_url = business.image_url;
// Creating the info-box
var markerInfo = document.createElement('div');
var title = document.createElement('strong'); // name
title.textContent = name;
var text0 = document.createElement('text'); // categories
text0.textContent = catStr;
var text1 = document.createElement('text'); // address
text1.textContent = address;
var text2 = document.createElement('text'); // reviews
text2.textContent = reviews + " reviews";
var text3 = document.createElement('text'); // rating
text3.textContent = rating + " stars";
// Appending the text to the info-box
markerInfo.appendChild(title);
markerInfo.appendChild(document.createElement('br'));
markerInfo.appendChild(text0);
markerInfo.appendChild(document.createElement('br'));
markerInfo.appendChild(text1);
markerInfo.appendChild(document.createElement('br'));
markerInfo.appendChild(text2);
markerInfo.appendChild(document.createElement('br'));
markerInfo.appendChild(text3);
// create the marker on its according position and append into array
var marker = new google.maps.Marker({
map: map,
position: coord
});
// change the opacity of the markers according to rating
if (rating >= 4) {
marker.setOpacity(1.0);
} else if (rating >= 2.5 && rating < 4) {
marker.setOpacity(0.8);
} else if (rating < 2.5) {
marker.setOpacity(0.6);
}
// set the info-box to the marker on click
infoWindow = new google.maps.InfoWindow;
marker.addListener('click', function() {
console.log("Registering");
infoWindow.setContent(markerInfo);
infoWindow.open(map, marker);
});
markersArray.push(marker);
})(i);
}
}
};
request.open('GET', url); // initialize the request
request.send(); // send the request
}

Lets see if this helps...
In this batch of code you are building the infobox content but not setting it until the click event.
// set the info-box to the marker on click
infoWindow = new google.maps.InfoWindow;
marker.addListener('click', function() {
console.log("Registering");
infoWindow.setContent(markerInfo);
infoWindow.open(map, marker);
});
try moving the line that sets the content outside the click event. you should only need to set it once anyway
infoWindow = new google.maps.InfoWindow;
infoWindow.setContent(markerInfo);
marker.addListener('click', function() {
console.log("Registering");
infoWindow.open(map, marker);
});

Related

sorting marker in google map according to user location

I have a list of events that I display as markers on a map(its web application/site) and I would like to show only events in a certain distance (10 KM) from the user current location So, how can I combine this 2
//User Location
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(
function (position) {
var currentLatitude = position.coords.latitude;
var currentLongitude = position.coords.longitude;
// alert ("Latitude"+currentLatitude+"Longitude"+currentLongitude);window.mapServiceProvider(position.coords.latitude,position.coords.longitude);
// console.log(position);
}
);
}
//List of location from the Db.
var markers = #Html.Raw(Json.Encode(Model.UpcomingLectureGigs));
//Set All merkers on the map
window.onload = function (a) {
var mapOptions = {
center: new window.google.maps.LatLng(window.markers[0].Latitude, window.markers[0].Longitude),
zoom: 12,
mapTypeId: window.google.maps.MapTypeId.ROADMAP
};
var infoWindow = new window.google.maps.InfoWindow();
var map = new window.google.maps.Map(document.getElementById("dvMap"), mapOptions);
for (var i = 0; i < window.markers.length; i++) {
var data = window.markers[i];
var myLatlng = new window.google.maps.LatLng(data.Latitude, data.Longitude);
// console.log(data.Latitude, data.Longitude);
var marker = new window.google.maps.Marker({
position: myLatlng,
draggable: true,
animation: google.maps.Animation.DROP,
get map() { return map; }
});
(function (marker, data) {
window.google.maps.event.addListener(marker,
"click",
function (e) {
infoWindow.setContent(data
.Venue +
" " +
data.Genre.Name +
" " +
data.DateTime.toString("dd/mm/yy"));
//.toISOString().split("T")[0]);
// .format('MM/DD h:mm');
infoWindow.open(map, marker);
});
})(marker, data);
};
};
You can use a geometry library to calculate distance in meters between the user location and marker.
https://developers.google.com/maps/documentation/javascript/reference#spherical
The code snapshot to filter markers may be something like
var markers_filtered = markers.filter(function(marker, index, array) {
var myLatlng = new window.google.maps.LatLng(marker.Latitude, marker.Longitude);
return google.maps.geometry.spherical.computeDistanceBetween(userLatLng, myLatlng) < 10000;
});
for (var i = 0; i < markers_filtered.length; i++) {
//Your stuff here
}
You should add libraries=geometry parameter when you load Maps JavaScript API.
https://developers.google.com/maps/documentation/javascript/geometry

Clear Polyline from Google Maps and then restart it

I am playing around with the Google Maps API v3 for a project I am building.The premise is the user can draw a route on the map however at any point can clear it and start again. The issue I am having is restarting the polyline after the map has been cleared. Whilst the markers appear the polyline does not.
I have discovered that the line poly.setMap(null); only hides the polyline that is draw and doesn't clear it therefore it is understandable why the line doesn't show. However on finding this out I now need to know how to clear it and how it can be restarted.
The code is below:
var poly;
var map, path = new google.maps.MVCArray(),
service = new google.maps.DirectionsService(), poly;
var removepolyline;
var geocoder;
var bounds = new google.maps.LatLngBounds();
var markersArray = [];
var destinationIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=D|FF0000|000000';
var originIcon = 'https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=O|FFFF00|000000';
var count = 0;
var countname = 0;
var latitude_start;
var longitude_start;
function initialize() {
var mapOptions = {
zoom: 16,
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
geocoder = new google.maps.Geocoder();
///Geolocation
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Current Location'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
///Place fallback loop
}
///Allows the polyline to follow the road
poly = new google.maps.Polyline({ map: map });
google.maps.event.addListener(map, "click", function(evt) {
if (path.getLength() === 0) {
//Enters on first click
path.push(evt.latLng);
poly.setPath(path);
} else {
//Enters on second click
service.route({
origin: path.getAt(path.getLength() - 1),
destination: evt.latLng,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length;
i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
});
}
var latitude_longitude = evt.latLng;
var latitude = evt.latLng.lat();
var longitude = evt.latLng.lng();
//alert(latitude_longitude);
//alert(latitude);
// alert(longitude);
///Saves the first click location
if(count === 0){
var latitude_start = evt.latLng.lat();
var longitude_start = evt.latLng.lng();
var firstlat = latitude_start;
var firstlng = longitude_start;
/////Trying to calculate distance
var origin1 = new google.maps.LatLng(firstlat, firstlng);///1st click - never changes
document.getElementById("origin1").value = origin1;
document.getElementById("startpoint").value = origin1;
////Calculate distance
var destinationA = new google.maps.LatLng(latitude, longitude); ///Most recent click
document.getElementById("destination").value = destinationA; ////Stores Destination
var origin1 = document.getElementsByName('origin1')[0].value ////Retrieves value from text box
count ++;
}else{
var origin1 = document.getElementsByName('destination')[0].value ////Retrieves value from text box
////Calculate distance
var destinationA = new google.maps.LatLng(latitude, longitude); ///Most recent click
document.getElementById("destination").value = destinationA; ////Stores Destination
}
////Calculate distance
var servicetime = new google.maps.DistanceMatrixService();
servicetime.getDistanceMatrix(
{
origins: [origin1],
destinations: [destinationA],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
}, callback);
});
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
///Enters the if it is the first loop round/first click
if(countname === 0){
document.getElementById("startpointname").value = origins;
countname ++;
}
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('outputDiv');
outputDiv.innerHTML = '';
//deleteOverlays(); ////
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
//addMarker(origins[i], false);
for (var j = 0; j < results.length; j++) {
outputDiv.innerHTML += start + ' to ' + destinations[j]
+ ': ' + miles + ' miles in '
+ overalltime + ' minutes <br>';
}
}
}
}
// Add a listener for the click event
google.maps.event.addListener(map, 'click', addLatLng);
}////Function initialize ends here
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
/**
* Handles click events on a map, and adds a new point to the Polyline.
* #param {google.maps.MouseEvent} event
*/
function addLatLng(event) {
// Add a new marker at the new plotted point on the polyline.
var marker = new google.maps.Marker({
position: event.latLng,
title: '#' + path.getLength(),
map: map
});
markersArray.push(marker);
}///Function addLatLng ends here
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
}
function clearall() {
poly.setMap(null);//Just hiding them
clearMarkers();
markersArray = [];
///////////////////CLEAR ALL VALUES IN HERE i.e. miles, time etc and CLEAR MARKERS
restartpolyline();
}
//////////////////////////////////////////WHEN CLEARED THE CODE NEEDS INTITALISING AGAIN
function restartpolyline(){
//alert("Restart");
}
//https://developers.google.com/maps/documentation/javascript/reference#Polyline
google.maps.event.addDomListener(window, 'load', initialize);
To view what currently happens view the following link: http://kitlocker.com/sotest.php
Instead of poly.setMap(null); call path.clear();
Polyline is just an array of LatLng objects, not individual Polylines, which you can then loop over to remove them all.
You can make it invisible or remove it from the map by looping it like this:
var size = poly.length;
for (i=0; i<size; i++)
{
poly[i].setMap(null);
}

Adding links that open an info window in Google maps API v3

Having trouble adding links that will center and open an info window on my google map. The markers and their info windows work fine within the map itself.
The real problem is constructing an object that my onclick function can reference properly. My object oriented Javascript knowledge is shaky and I'm just not seeing the solution.
The map is loaded via a function that's called on page load and I have a seperate function that's called on click of an href within the page.
Code is below.
function addMap(addressesJSON, id){
var addresses = eval('(' + addressesJSON + ')');
var cenLat = 41.677389;
var cenLng = -72.384294;
var latLow = 41.4;
var lngLow = -72.8;
var latHigh = 41.8;
var lngHigh = -71.9;
if (addresses.length){
for (var i in addresses){
addresses[i].lat = parseFloat(addresses[i].lat);
addresses[i].lng = parseFloat(addresses[i].lng);
if (i == 0){
latLow = addresses[i].lat;
latHigh = addresses[i].lat;
lngLow = addresses[i].lng;
lngHigh = addresses[i].lng;
} else {
if (addresses[i].lat < latLow){
latLow = addresses[i].lat;
}
if (addresses[i].lat > latHigh){
latHigh = addresses[i].lat;
}
if (addresses[i].lng < lngLow){
lngLow = addresses[i].lng;
}
if (addresses[i].lng > lngHigh){
lngHigh = addresses[i].lng;
}
}
address = "<span style=\"color: #0000ff\">" + addresses[i].name + "</span><br/>" + addresses[i].address + "<br/>Directions: To - From";
addresses[i].address = address;
}
cenLat = (latLow + latHigh) / 2;
cenLng = (lngLow + lngHigh) / 2;
}
var mapOptions = {
center: new google.maps.LatLng(cenLat, cenLng),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// Display a map on the page
var map = new google.maps.Map(document.getElementById(id), mapOptions);
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();
for (var i in addresses){
var letter = addresses[i].letter;
var data = addresses[i].address;
var myLatlng = new google.maps.LatLng(addresses[i].lat, addresses[i].lng);
var latlng = new google.maps.LatLng(addresses[i].lat, addresses[i].lng);
bounds.extend(latlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: addresses[i].name,
icon: "http://maps.google.com/mapfiles/marker" + letter + ".png"
});
(function (marker, data) {
google.maps.event.addListener(marker, "click", function () {
// Center on marker
map.setCenter(marker.getPosition());
// Set the data for the info window
infowindow.setContent(data);
// show the infowindow
infowindow.open(map, marker);
});
})(marker, data);
}
map.fitBounds(bounds);
}
And the function that's fired onclick that I want to open the corresponding infowindow.
function moveCenter(lat, lng, letter){
google.maps.event.trigger(marker[letter], "click");
}
Any help on how to build a marker object array and have it be seen by my moveCenter function would be greatly appreciated.
Looks like you just need to add this line to your code:
markers[letter] = marker;
and change your function:
function moveCenter(lat, lng, letter){
google.maps.event.trigger(markers[letter], "click");
}
(make sure the markers array is in the global scope)
markers = [];
function addMap(addressesJSON, id){
var addresses = eval('(' + addressesJSON + ')');
var cenLat = 41.677389;
var cenLng = -72.384294;
var latLow = 41.4;
var lngLow = -72.8;
var latHigh = 41.8;
var lngHigh = -71.9;
if (addresses.length){
for (var i in addresses){
addresses[i].lat = parseFloat(addresses[i].lat);
addresses[i].lng = parseFloat(addresses[i].lng);
if (i == 0){
latLow = addresses[i].lat;
latHigh = addresses[i].lat;
lngLow = addresses[i].lng;
lngHigh = addresses[i].lng;
} else {
if (addresses[i].lat < latLow){
latLow = addresses[i].lat;
}
if (addresses[i].lat > latHigh){
latHigh = addresses[i].lat;
}
if (addresses[i].lng < lngLow){
lngLow = addresses[i].lng;
}
if (addresses[i].lng > lngHigh){
lngHigh = addresses[i].lng;
}
}
address = "<span style=\"color: #0000ff\">" + addresses[i].name + "</span><br/>" + addresses[i].address + "<br/>Directions: To - From";
addresses[i].address = address;
}
cenLat = (latLow + latHigh) / 2;
cenLng = (lngLow + lngHigh) / 2;
}
var mapOptions = {
center: new google.maps.LatLng(cenLat, cenLng),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// Display a map on the page
var map = new google.maps.Map(document.getElementById(id), mapOptions);
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();
for (var i in addresses){
var letter = addresses[i].letter;
var data = addresses[i].address;
var myLatlng = new google.maps.LatLng(addresses[i].lat, addresses[i].lng);
var latlng = new google.maps.LatLng(addresses[i].lat, addresses[i].lng);
bounds.extend(latlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: addresses[i].name,
icon: "http://maps.google.com/mapfiles/marker" + letter + ".png"
});
markers[letter] = marker;
(function (marker, data) {
google.maps.event.addListener(marker, "click", function () {
// Center on marker
map.setCenter(marker.getPosition());
// Set the data for the info window
infowindow.setContent(data);
// show the infowindow
infowindow.open(map, marker);
});
})(marker, data);
}
map.fitBounds(bounds);
}

Need to prevent a dropdown list being added over and over

I'm using the Google Maps code with PHP MySql, and as per the code from their developers site I've got the map working. However, as part of their code they add a menu (which contains all of the returned options) under the map. The problem is that when i carry out another search I get another added rather than the one that is already there being updated with the new information. I think that the problem is something to dow with the locationSelect object, I would appreciate some help with it:
//Variables that we need later
var map;
var markers = [];
var infoWindow;
var locationSelect;
var myLatLng = new google.maps.LatLng(40,-100);
var addmap = ('<div id="map" style="visibility:visible;"></div>');
var addLocationSelect = '</br><div id="locationSelectDiv"><select id="locationSelect"></select></div>';
var subject_text = "";
var subject_id = "";
function load(myLatlng) {
map = new google.maps.Map(document.getElementById("map"), {
center: myLatLng,
zoom: 3,
mapTypeId: 'roadmap',
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
google.maps.event.trigger(map, 'resize');
infoWindow = new google.maps.InfoWindow();
locationSelect = document.getElementById("locationSelect");
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
if (markerNum != "none"){
google.maps.event.trigger(markers[markerNum], 'click');
}
};
}
function searchLocations() {
var address = document.getElementById("addressInput").value;
var subject_text = $('#search_subject>option:selected').text();
var subject_id = $('#search_subject>option:selected').val();
console.log(address);
console.log(subject_text);
console.log(subject_id);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$('#container').replaceWith(addmap);
$("#map").slideDown("4000", function(){
$('#map').after(addLocationSelect);
load();
searchLocationsNear(results[0].geometry.location);
});
} else {
alert(address + ' not found');
}
});
}
function clearLocations() {
infoWindow.close();
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
markers.length = 0;
locationSelect.innerHTML = "";
var option = document.createElement("option");
option.value = "none";
option.innerHTML = "See all results:";
locationSelect.appendChild(option);
}
function searchLocationsNear(center) {
clearLocations();
var searchUrl = 'findlocations.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=20';
downloadUrl(searchUrl, function(data) {
var xml = parseXml(data);
var markerNodes = xml.documentElement.getElementsByTagName("marker");
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < markerNodes.length; i++) {
var name = markerNodes[i].getAttribute("name");
var address = markerNodes[i].getAttribute("address");
var distance = parseFloat(markerNodes[i].getAttribute("distance"));
var latlng = new google.maps.LatLng(
parseFloat(markerNodes[i].getAttribute("lat")),
parseFloat(markerNodes[i].getAttribute("lng")));
createOption(name, distance, i);
createMarker(latlng, name, address);
bounds.extend(latlng);
}
map.fitBounds(bounds);
locationSelect.style.visibility = "visible";
locationSelect.onchange = function() {
var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
google.maps.event.trigger(markers[markerNum], 'click');
};
});
}
function createMarker(latlng, name, address) {
var html = "<h3>" + name + "</h3><p>The biography will go here</p>";
var marker = new google.maps.Marker({
map: map,
position: latlng
});
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
markers.push(marker);
}
function createOption(name, distance, num) {
var option = document.createElement("option");
option.value = num;
option.innerHTML = name + " is " + distance.toFixed(1) + "miles away";
locationSelect.appendChild(option);
}
createOption() does exactly as it says it creates a new option. If you want to add the results of a new search (including markers) you will need to add these to the existing locations.
pseudo code NOT tested
GLOBAL var flag = 0;\\Set to 0 for 1st Search
IN searchLocationsNear() add following
searchLocationsNear(center) {
if(flag ==0){//1st Search
clearLocations();
}else{//Sugsequent Searches
flag =1;
}
The problem is that the locationSelect select dropdown is added every time searchLocations function returns. I just moved it to the top of the function and it's added fresh every time the submit button is entered, which will only provide a single dropdown with the results for the map.
function searchLocations() {
$('#container').replaceWith(addmap);
var address = document.getElementById("addressInput").value;
alert(address);
var subject_text = $('#search_subject>option:selected').text();
var subject_id = $('#search_subject>option:selected').val();
console.log(address);
console.log(subject_text);
console.log(subject_id);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({address: address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$("#map").slideDown("4000", function(){
load();
searchLocationsNear(results[0].geometry.location);
});
} else {
alert(address + ' not found');
}
});
}

Google Maps V3: Updating Markers Periodically

I've followed the PHP/MYSQL tutorial on Google Maps found here.
I'd like the markers to be updated from the database every 5 seconds or so.
It's my understanding I need to use Ajax to periodicity update the markers, but I'm struggling to understand where to add the function and where to use setTimeout() etc
All the other examples I've found don't really explain what's going on, some helpful guidance would be terrific!
This is my code (Same as Google example with some var changes):
function load() {
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(37.80815648152641, 140.95355987548828),
zoom: 13,
mapTypeId: 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// Change this depending on the name of your PHP file
downloadUrl("nwmxml.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var host = markers[i].getAttribute("host");
var type = markers[i].getAttribute("active");
var lastupdate = markers[i].getAttribute("lastupdate");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + "Host: </b>" + host + "<br>" + "<b>Last Updated: </b>" + lastupdate + "<br>";
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
bindInfoWindow(marker, map, infoWindow, html);
}
});
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}
I hope somebody can help me!
Please note I have not tested this as I do not have a db with xml handy
First of all you need to split your load() function into a function that initializes the map & loads the markers on domready and a function that you will use later to process the xml & update the map with. This needs to be done so you do not reinitialize the map on every load.
Secondly you need to decide what to do with markers that are already drawn on the map. For that purpose you need to add them to an array as you add them to the map. On second update you have a choice to either redraw the markers (rebuild the array) or simply update the existing array. My example shows the scenario where you simply clear the old markers from the screen (which is simpler).
//global array to store our markers
var markersArray = [];
var map;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center : new google.maps.LatLng(37.80815648152641, 140.95355987548828),
zoom : 13,
mapTypeId : 'roadmap'
});
var infoWindow = new google.maps.InfoWindow;
// your first call to get & process inital data
downloadUrl("nwmxml.php", processXML);
}
function processXML(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
//clear markers before you start drawing new ones
resetMarkers(markersArray)
for(var i = 0; i < markers.length; i++) {
var host = markers[i].getAttribute("host");
var type = markers[i].getAttribute("active");
var lastupdate = markers[i].getAttribute("lastupdate");
var point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + "Host: </b>" + host + "<br>" + "<b>Last Updated: </b>" + lastupdate + "<br>";
var icon = customIcons[type] || {};
var marker = new google.maps.Marker({
map : map,
position : point,
icon : icon.icon,
shadow : icon.shadow
});
//store marker object in a new array
markersArray.push(marker);
bindInfoWindow(marker, map, infoWindow, html);
}
// set timeout after you finished processing & displaying the first lot of markers. Rember that requests on the server can take some time to complete. SO you want to make another one
// only when the first one is completed.
setTimeout(function() {
downloadUrl("nwmxml.php", processXML);
}, 5000);
}
//clear existing markers from the map
function resetMarkers(arr){
for (var i=0;i<arr.length; i++){
arr[i].setMap(null);
}
//reset the main marker array for the next call
arr=[];
}
function bindInfoWindow(marker, map, infoWindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(map, marker);
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
request.onreadystatechange = function() {
if(request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
setInterval(function() {
downloadUrl("conection/cargar_tecnicos.php", function(data) {
var xml = data.responseXML;
markers = xml.documentElement.getElementsByTagName("marker");
removeAllMarkers();
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var fecha = markers[i].getAttribute("fecha");
var id_android = markers[i].getAttribute("id_android");
var celular = markers[i].getAttribute("celular");
var id = markers[i].getAttribute("id");
var logo = markers[i].getAttribute("logo");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<div class='infowindow'>"
+"<br/><div style='text-align:center;'><img src="+logo+"><br/>"
+"<b>" + name + "</b></div><br/>"
+"<br/><label><b>Celular:</b></label>" + celular+""
+"<br/><label><b>Id Android:</b></label>" + id_android+""
+"<br/><label><b>Fecha y Hora:</b></label>" + fecha+""
+"<br/><br/><div style='text-align:center;'><a><input style=';' id='pop' type='image' value='"+id+"' class='ASD' img src='img/vermas.png' title='Detalles'/></a></div></div>";
var icon = customIcons[type] || {};
marker[i] = new google.maps.Marker({
position: point,
icon: icon.icon,
shadow: icon.shadow,
title:name
});
openInfoWindow(marker[i], map, infoWindow, html);
marker[i].setMap(map);
}
});
},10000);
}
function removeAllMarkers(){// removes all markers from map
for( var i = 0; i < marker.length; i++ ){
marker[i].setMap(null);
}
}

Categories

Resources