I am trying to make a website using the google maps javascript API to find hotels around a city, and compare the distances between each hotel to user-entered locations in order to find the hotel closest to all the locations they want to visit.
First it calculates the coordinates of the user-entered locations (using the geocoding API which works fine), and then it gets the coordinates/google places information of the hotels.
Using the google.maps.geometry.spherical.computeDistanceBetween(LatLng a, LatLng b); to get the distance between each hotel and the user-entered addresses, the function returns this error:
Uncaught TypeError: Cannot read property 'lat' of undefined
However, both of the LatLng arguments I pass to the function don't seem to be null or undefined.
Each of the if(location1 != ""), if(location2 != ""), etc. code blocks checks if the LatLng objects for either the hotel or the location is null and prints an error if it is, but these errors are not printed in the javascript console when i run the webpage.
Here is the Javascript and HTML in question:
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
var nearbyHotels = [];
var cityCoordinates;
var cityCoordinatesLatLng;
function findHotels()
{
var nearbyHotelsLat = [];
var nearbyHotelsLong = [];
var locationScores1 = [];
var locationScores2 = [];
var locationScores3 = [];
var locationScores4 = [];
var locationScores5 = [];
var avgScores = [];
var geocoder = new google.maps.Geocoder();
var cityAddress = document.getElementById('locations_cityField').value;
var radiusSearch = parseInt(document.getElementById('locations_rangeField').value);
var location1 = document.getElementById('locations_location1').value;
var location2 = document.getElementById('locations_location2').value;
var location3 = document.getElementById('locations_location3').value;
var location4 = document.getElementById('locations_location4').value;
var location5 = document.getElementById('locations_location5').value;
var location1LatLng;
var location2LatLng;
var location3LatLng;
var location4LatLng;
var location5LatLng;
if(location1 != "" && location1 != undefined)
location1LatLng = geocodeAddress(geocoder, location1);
if(location2 != "" && location2 != undefined)
location2LatLng = geocodeAddress(geocoder, location2);
if(location3 != "" && location3 != undefined)
location3LatLng = geocodeAddress(geocoder, location3);
if(location4 != "" && location4 != undefined)
location4LatLng = geocodeAddress(geocoder, location4);
if(location5 != "" && location5 != undefined)
location5LatLng = geocodeAddress(geocoder, location5);
console.log(location1LatLng);
var cityLoc = geocodeAddress(geocoder, cityAddress);
setTimeout(function(){
var coordSplit = cityCoordinates.split(",");
var lati = parseFloat(coordSplit[0]);
var lngi = parseFloat(coordSplit[1]);
var city = {lat: lati, lng: lngi};
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: city,
radius: radiusSearch,
types: ['lodging']
}, callback);
map.setCenter(cityLoc);
setTimeout(function(){
console.log("nearbyHotels.length: " + nearbyHotels.length);
if(location1 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location1LatLng == "")
{
console.log("NULL LOCATION1LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (1) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location1LatLng, hotelLatLng);
locationScores1.push(dist);
}
}
if(location2 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location2LatLng == "")
{
console.log("NULL LOCATION2LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (2) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location2LatLng, hotelLatLng);
locationScores2.push(dist);
}
}
if(location3 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location3LatLng == "")
{
console.log("NULL LOCATION3LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (3) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location3LatLng, hotelLatLng);
locationScores3.push(dist);
}
}
if(location4 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location4LatLng == "")
{
console.log("NULL LOCATION4LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (4) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location4LatLng, hotelLatLng);
locationScores4.push(dist);
}
}
if(location5 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location5LatLng == "")
{
console.log("NULL LOCATION5LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (5) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location5LatLng, hotelLatLng);
locationScores5.push(dist);
}
}
for(var i = 0; i < nearbyHotels.length; i++)
{
var avgDist;
var numLocations = 0;
if(location1 != "")
{
numLocations++;
avgDist += locationScores1[i];
}
if(location2 != "")
{
numLocations++;
avgDist += locationScores2[i];
}
if(location3 != "")
{
numLocations++;
avgDist += locationScores3[i];
}
if(location4 != "")
{
numLocations++;
avgDist += locationScores4[i];
}
if(location5 != "")
{
numLocations++;
avgDist += locationScores5[i];
}
avgDist = avgDist / numLocations;
avgScores.push(avgDist);
}
var avgScoresSorted = avgScores.sort(function (a, b) {
return b - a;
});
for(var i = 0; i < avgScoresSorted.length; i++)
{
var index = avgScores.indexOf(avgScoresSorted[i]);
var hotelName = nearbyHotels[index].name;
var hotelAddress = nearbyHotels[index].vicinity;
document.getElementById("displayHotelsDiv").innerHTML += (i + 1) + ": " + hotelName + " (" + hotelAddress + ") - LocationScore: " + avgScoresSorted[i];
}
}, 10000);
}, 5000);
}
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
createMarker(results[i]);
nearbyHotels.push(results[i]);
}
}
}
function initSearchButtonListener()
{
document.getElementById('button_searchhotels').addEventListener('click', function() {
findHotels();
});
initMap();
}
function geocodeAddress(geocoder, address) {
console.log("address " + address);
console.log("geocoder " + geocoder);
geocoder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var coords = results[0].geometry.location.toString();
console.log("CoordsRaw: " + coords)
var coordsNoFirst = coords.substring(1);
var coordsNoLast = coordsNoFirst.slice(0, -1);
cityCoordinates = coordsNoLast;
console.log(cityCoordinates);
return results[0].geometry.location;
} else {
alert('Could not convert an address to latitude/longitude for the google maps API: ' + status);
}
});
}
And the html that goes along with it:
<div class="container" id="locations">
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location1" placeholder="Enter address of the 1st location">
</div>
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location2" placeholder="Enter address of the 2nd location">
</div>
</div>
<br></br>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location3" placeholder="Enter address of the 3rd location">
</div>
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location4" placeholder="Enter address of the 4th location">
</div>
</div>
<br></br>
<div class="row" style="text-align:center">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location5" placeholder="Enter address of the 5th location">
</div>
</div>
<br></br>
<div class="row">
<div id="locationField">
<input type="text" class="form-control" id="locations_cityField" placeholder="Enter a city" type="text" />
</div>
<div id="rangeField">
<input type="text" class="form-control" id="locations_rangeField" placeholder="Enter a search radius in meters (from the city center)" type="text" />
</div>
</div>
<div style="text-align:center">
<div id="map" style="width: 800px; height: 400px;"></div>
</div>
<button id="button_searchhotels" class="btn btn-success btn-lg">Search</button>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBVVnR7yKErwMDd6yC-GzVpRXFvNTtoKhQ&signed_in=true&libraries=places,geometry&callback=initSearchButtonListener"
async defer></script>