Google Maps Geocoder - Get values into callback - asynchronous

I have some troubles with the Geocoder from Google Maps.
The main idea is, that I have a list with estates (flat, house, ...) in it and I want to search for Points of Interest (POIs; university, cafe, etc.) nearby the estates with some given range. There is no problem, it works fine.
BUT what I want to do now is, to "delete", or better said, make the markers invisible, which have no Points of Interest in the given range nearby.
In the code below you will see, that I have the geocode in a for loop, and for every estate which it gets it sets the POIs. Now I want to give over the estates which it uses at this time, checks if there are results nearby, if not it should set the marker of the estate on map to null. The problem is, that I can't give over the id of the estate, so I can set the marker to null with this specific ID.
Right now it works partially, but it always deletes the markers randomly. (Currently it is done with some counter to delete the index... but I want to delete it with the id).
So, the main question is, how can I hand over the current ID of the estate from the for loop into the callback and delete the marker with the same ID?
To understand the code i should say that "immo" or "immobilien" is the german word for estates.
Here's the code:
function geocodePoi(geocoder, resultsMap) {
var poiCat = document.getElementById("poi").value;
poiList.push(poiCat);
var address = document.getElementById('address').value;
var poi = document.getElementById('poi').value;
var radius = document.getElementById('range').value;
var poiArray = [];
poiArray.push(poi);
var latlng;
geocoder.geocode({'address': address}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
resultsMap.setCenter(results[0].geometry.location);
latlng = results[0].geometry.location;
latlngDic = {lat: latlng.lat(), lng: latlng.lng()};
infowindow = new google.maps.InfoWindow();
for (i = 0; i < immobilien.length; i++) {
currentImmo = immobilien[i].id;
currentImmoList.push(currentImmo);
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: new google.maps.LatLng(immobilien[i].longitude,
immobilien[i].latitude),
radius: radius,
types: poiArray
}, callback);
}
}
else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
function callback(results, status) {
if (status === "ZERO_RESULTS") {
setMapOnAllImmo(null, count);
count = count + 1;
}
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
count += 1;
}
}

Related

How do I auto zoom to view multiple markers using the Google Geocoding API?

I'm using the Google Geocoding API to build a map that puts markers on whichever locations are requested. At the moment it auto-zooms to each location individually - how do I use fit Bounds to make it zoom to all the locations, i.e. if Sydney is input first, then London, how do I ask it to auto-zoom so the user can view both?
I'm very new to this so any advice welcome!
I've tried many different way to use bounds, fit Bounds, marker.length etc but none of it works or makes much sense to me.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 45.1497, lng: 100.0943},
zoom: 3
});
var geocoder = new google.maps.Geocoder()
var step1 = location.href.split("?")[1].split("=")[1]
$("#address1").val(step1);
geocodeAddress1(geocoder, map);
$(".steps").keypress(function() {
if (event.which == 13) {
geocodeAddress(geocoder, map);
}
})
};
var labelIndex = 0;
function geocodeAddress1(geocoder, resultsMap) {
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var address = $("#address1").val();
geocoder.geocode({'address': address}, function(results, status) {
if (status === 'OK') {
resultsMap.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: resultsMap,
label: labels[labelIndex++ % labels.length],
position: results[0].geometry.location
});
} else {
alert('Search not successful: ' + status);
}
})
};
function geocodeAddress(geocoder, resultsMap) {
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var nextstep = "#".concat(event.target.id);
debugger;
var address = $(nextstep).val();
geocoder.geocode({'address': address}, function(results, status) {
if (status === 'OK') {
resultsMap.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: resultsMap,
label: labels[labelIndex++ % labels.length],
position: results[0].geometry.location
});
} else {
alert('Search not successful: ' + status);
}
})
};
You need to store all the markers/loations first in an array each time you click "Geocode", then call bounds.extend() for each location searched to contain the given point and lastly call resultsMap.fitBounds() to set the viewport to contain the given bounds.
var marker = new google.maps.Marker({
map: resultsMap,
position: results[0].geometry.location
});
markerCount++;
markers[markerCount] = marker;
// extend the bounds here to consider each location
bounds.extend(results[0].geometry.location);
// then call fitBounts()
resultsMap.fitBounds(bounds);
Here's a working sample in JSFiddle.
Hope it helps!

google maps API v3 : computing distance between 2 points on a polyline

I am a bit confused with my code and I don't really know which way to go.
Let's consider I have a car marker that is running through a polyline.
I change its position each 500 ms by setting a timer :
function animate() {
var p = polyline.GetPointAtDistance(distanceFromBeginning);
carMarker.setPosition(p);
distanceFromBeginning += step;
timerHandle = setTimeout("animate("+(distanceFromBeginning)+")", tick);
}
I also added the fact that my car can be dragged on the route :
google.maps.event.addDomListener(carMarker, 'dragend', function(e) {
var p = find_closest_point_on_path(e.latLng,polyline.getPath());
console.log("position is : " + p);
carMarker.setPosition(p);
console.log("dragend")
});
Now that I have a new position after dragging the car on the polyline, how can I get its distance from the start location so I can update it correctly in my timer?
Once you have the coordinates for the end location (lets call the "destination"), and assuming that on your 'dragend' event you set the coordinates for the car (let call "origin") location you can call this function on your listener:
function calculateDistances() {
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destination],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, callback);
}
function callback(response, status) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
console.log(results[j].distance.text);
console.log(results[j].duration.text);
}
}
}
}
Check this example on jsfiddle based on the Google documentation(look the result on your console)
Fell free to reply if you need more help with this code or if it's not what you want.

Creating multiple individual info windows alongside multiple markers in Google Maps

My project searches the eBay API (using PHP and returns simpleXML) and returns the postcodes of multiple items (5 at the moment). Then uses this information to plot markers on a Google map on my website. What I am trying to do is create multiple info windows along with these markers so I can also return information from the eBay auction and put it in the info window (link to auction, picture of item etc.) but I am having no luck! I cannot seem to get the closures right in my loop and I keep getting the last postcode in the array displayed in the info window rather than the postcode actually associated with that marker (just doing this for test purposes).
What am I doing wrong? Any information will be helpful.
This is my code at the moment:
for (var i = 0; i < msg.length; i++) {
info = msg[i];
console.log(info);
geocoder.geocode( { 'address': msg[i]}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
icon: image,
position: results[0].geometry.location
})
listenMarker(marker);
markerBounds.extend(results[0].geometry.location);
map.fitBounds(markerBounds);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function listenMarker (marker){
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(info);
infoWindow.open(map, this);
});
You are need to use a function closure on the geocoder call as well (not tested), looks like you might have a problem with your listMarker function also (seems to be missing the definition of "info", if you are depending on the global value of that, that could be your problem):
function geocodeAddress(msg)
{
geocoder.geocode( { 'address': msg}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.DROP,
icon: image,
position: results[0].geometry.location
})
listenMarker(marker, msg);
markerBounds.extend(results[0].geometry.location);
map.fitBounds(markerBounds);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
for (var i = 0; i < msg.length; i++) {
info = msg[i];
console.log(info);
geocodeAddress(msg[i]);
}
function listenMarker (marker, info){
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(info);
infoWindow.open(map, this);
});

Google Maps API V3: pass marker coordinate to google directions service request

Users search my map with the Google places API which adds markers to my map. I have a click event inside each markers infowindow to get directions to that marker.
How do I pass the coordinates of the selected marker to my google directions service request?
So far I declared var placeLoc = null; as a global variable. I defined placeLoc=place.geometry.location; inside my create marker function. Then I have:
function calcRoute() {
var start = myLatLng;
var end = placeLoc;
var request = {
origin: start,
destination: end,
travelMode: google.maps.DirectionsTravelMode.BICYCLING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
The function renders directions to the wrong marker. I am guessing that it is just giving directions to the first marker in the array returned after the search and not the actual marker I selected. How do I provide the directions request the coordinates of a selected marker?
Below is the code that places the search results into the place variable:
google.maps.event.addListener(searchBox, 'places_changed', function() {
var places = searchBox.getPlaces();
// alert("getPlaces returns "+places.length+" places");
for (var i = 0; i < gmarkers.length; i++) {
gmarkers[i].setMap(null);
}
gmarkers = [];
var bounds = new google.maps.LatLngBounds();
for (var i = 0, place; place = places[i]; i++) {
var place = places[i];
createMarker(place);
bounds.extend(place.geometry.location);
}
map.fitBounds(bounds);
// if (markers.length == 1) map.setZoom(17);
});
Something like this?
function createMarker(options) {
var marker = new google.maps.Marker(options);
google.maps.event.addListener(marker, 'click', function() {
placeLoc = marker.getPosition();
calcRoute();
});
return marker;
}

Google Places Api: Not able to display all search results

I am unable to display all the results requested from the Google Places Api..
var Latlng = new google.maps.LatLng(Latitute, Longitute);
map = new google.maps.Map(document.getElementById('map_canvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: Latlng,
zoom: 10});
var request = {location: Latlng,types: [type]};
var service = new google.maps.places.PlacesService(map);
service.search(request, callback);
}
function callback(results,status,pagination) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
if (pagination.hasNextPage) {
pagination.nextPage(); }}}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({map: map,zIndex: 100,position: place.geometry.location});
var request = {reference : place.reference,};
service = new google.maps.places.PlacesService(map);
service.getDetails(request, function detailsDisplay(details, status){
if (status === google.maps.places.PlacesServiceStatus.OK) {
console.log(status);
$('#placesdata').append('<tr><td><a href='+details.url+'>' + details.name+ '</a></td></tr>');
} else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function() {
createMarker(place);
}, 200);}});} };
i used pagination and getting 60 results but only can display 20..and 40 using settimeout() function...getting the following error: Uncaught TypeError: Cannot read property 'length' of null. Any clue?
Most likely you are getting OVER_QUERY_LIMIT on line:
if (status == google.maps.places.PlacesServiceStatus.OK)
because you are already creating Markers, which eats up your quota.
Try queuing the details requests for after you have all the list completed, and adding the same timeout logic to check for google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT on this line.
For example you could say:
if (pagination.hasNextPage) {
//add all places to the list
setTimeout('pagination.nextPage()',2000);
} else {
createMarkers(placesList);
}
btw. the Places equivalent of google.maps.GeocoderStatus.OVER_QUERY_LIMIT is google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT and you should use this when using Places.
HTH
I have done all those effort. Thanks for you guys for posting but i got solution. really a good solution. See working example below.
When you call this method to check if it has pages or not
if(pagination.hasNextPage){
pagination.nextPage(); // let this do recursive loop against request.
}
// when nextPage() request finishes
if(pagination.b == null){
// here pagination.b has next page token. so it return null when last request sent.
createMarkers(placesList);
}

Resources