I have edited my code below and put the full JS. I am trying to extract a list of places near a given zipcode or city. My first step would be to take the zipcode or city name and get the latlng coordinates and then get the list of places. I am getting the following errors "Cannot call method 'geocode' of undefined " & " Cannot read property 'offsetWidth' of null" Any help will be greatly appreciated.
var placesList;
var geocoder;
var map;
function initialize() {
map = new google.maps.Map(document.getElementById('map'));
geocoder = new google.maps.Geocoder();
}
function getLatLng(address, callback) {
geocoder.geocode({
address: address
}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var location = new google.maps.LatLng(result.lat(), result.lng());
map.setCenter(location);
var marker = new google.maps.Marker({
map: map,
position: location
});
callback(location);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
getLatLng('14235', function (latLngLocation) {
var pyrmont = latLngLocation;
var request = {
location: pyrmont,
radius: 5000,
types: ['park', 'zoo']
};
placesList = document.getElementById('places');
var service = new google.maps.places.PlacesService(map);
service.nearbySearch(request, callback);
var request1 = {
reference: place.reference
};
service.getDetails(request1, createMarkers);
function callback(results, status, pagination) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
return;
} else {
for (var i = 0; i < results.length; i++) {
var markerPlace = results[i];
createMarkers(markerPlace, status);
}
if (pagination.hasNextPage) {
var moreButton = document.getElementById('more');
moreButton.disabled = false;
google.maps.event.addDomListenerOnce(moreButton, 'click',
function () {
moreButton.disabled = true;
pagination.nextPage();
});
}
}
}
function createMarkers(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var bounds = new google.maps.LatLngBounds();
var image = {
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(25, 25)
};
var marker = new google.maps.Marker({
map: map,
icon: image,
title: place.name,
position: place.geometry.location
});
placesList.innerHTML += '<li>' + place.name + '<br>' +
(place.formatted_address ? place.formatted_address : place.vicinity) + '</li>';
bounds.extend(place.geometry.location);
map.fitBounds(bounds);
}
}
});
google.maps.event.addDomListener(window, 'load', initialize);
Your address is not a string, it is a number:
var address = 14235;
The API expects the "address" in the GeocoderRequest to be a string that looks like a postal address. If you want it to be a string, enclose it in quotes (although I'm not sure what you expect the geocoder to return for a single number):
var address = "14235";
If you give the geocoder something that looks more like a complete address, it will work better.
You also have a problem with the asynchronous nature of the geocoder (a FAQ), you can't return the result of an asynchronous function, you need to use it in the callback function.
What you have to understand is that the geocode API is asynchronous; you're trying to assign the results variable to pyrmont before it's ready. To achieve what you want you're going to need to use a callback. Plus there's some other things wrong with how you're dealing with latLng attributions. Anyway, here's how I think your code should look:
var map, geocoder; // global vars
// retain your initialize function
function initialize() {
map = new google.maps.Map(document.getElementById('map'), options);
geocoder = new google.maps.Geocoder();
}
// but separate out your code into a new function that accepts an address
// and a callback function.
function getLatLng(address, callback) {
geocoder.geocode({ address: address }, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
// assign a new Google latLng object to `location`
var location = new google.maps.LatLng(result.lat(), result.lng();
// set the center of the map and position using the latlng object
map.setCenter(location);
var marker = new google.maps.Marker({
map: map,
position: location;
});
// call the callback with the latlng object as a parameter.
callback(location);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
// call the `getLatLng` function with an address and a callback function
getLatLng('14235', function (latLngLocation) {
var pyrmont = latLngLocation;
});
Related
Input: user will select city and place category.
Output: google map with all places that have same category in that city.
How i can do it with google map APIs.
When i try to use places API it’s return json with geographic data but i cant use it with JavaScript or jQuery Json request.
$.getJSON( "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=1500&type=restaurant&keyword=cruise&key=YOUR_API_KEY", function( json ) {
console.log( "JSON Data: " + json );
});
But browser log don’t show any output.
Any example code for best way to implement my idea??!
Thank you
You're probably looking for the client-side Places Library's Nearby Search service. Take a look at this working jsfiddle.
JS code below:
var map;
var service;
var infowindow;
function initialize() {
var pyrmont = new google.maps.LatLng(-33.8665433, 151.1956316);
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
var request = {
location: pyrmont,
radius: '500',
type: ['restaurant']
};
service = new google.maps.places.PlacesService(map);
service.nearbySearch(request, callback);
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
var place = results[i];
createMarker(results[i]);
}
}
}
function createMarker(place) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
Hope this helps!
with this code you need only to provide city name and place types or that you can find here:
https://developers.google.com/places/web-service/supported_types
output will show 20 places in same city with type that you passed.
<script>
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
var map;
var service;
var infowindow;
var city;
function initMap() {
var cityName = document.getElementById('cityInput').value; // text input html tag
var type = document.getElementById('subCategory').value; // select input html tag
map = new google.maps.Map(document.getElementById('map'), {zoom: 14});
var cityRequest = {
query: cityName,
fields: ['name', 'geometry'],
};
//alert("find!! : " + cityName);
service = new google.maps.places.PlacesService(map);
service.findPlaceFromQuery(cityRequest, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
let city = results[0].geometry.location;
map.setCenter(city);
infowindow = new google.maps.InfoWindow();
//alert(type);
var request = {
location: city,
radius: '1000',
query: type
};
//radius is size of search area
service.textSearch(request, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) { // adding places to map
createMarker(results[i]);
}
//map.setCenter(results[0].geometry.location);
}
});
}
});
}
function createMarker(place) {
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);
});
}
</script>
With this code you will show map in you web page
<div id="map" style="height: 500px; "></div>
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&libraries=places&callback=initMap&language=ar" async defer></script>
I have a nearby search map, in every open of this map page, it returns the current position, now When I get the current position by coordinates, I want to reverse geocode it into an address name, the problem is I modified my code from this source: https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/geocoding-reverse
with
<script>
function getPosition() {
navigator.geolocation.getCurrentPosition(position => {
currentLatLon = [position.coords.latitude, position.coords.longitude];
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(...currentLatLon),
zoom: 20
});
var geocoder = new google.maps.Geocoder();
service = new google.maps.places.PlacesService(map);
document.getElementById("curr").innerHTML=currentLatLon;
document.getElementById("address").value=currentLatLon;
geocodeLatLng(geocoder,map,infowindow);
});
}
function geocodeLatLng(geocoder, map, infowindow) {
var input = document.getElementById('curr').value;
var latlngStr = input.split(',');
var latlng = {lat: parseFloat(latlngStr[0]), lng: parseFloat(latlngStr[1])};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
if (results[0]) {
map.setZoom(11);
var marker = new google.maps.Marker({
position: latlng,
map: map
});
infowindow.setContent(results[0].formatted_address);
infowindow.open(map, marker);
} else {
window.alert('No results found');
}
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
}
</script>
this should return the place name in the map which is like the source code I copied from above
https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/geocoding-reverse, what could be wrong in my modification? I have an error in the console when I run my modified code, error in the console
Here's my full code without the api key: https://pastebin.com/BhEqRsq0
You set the lat/lng coordinates to the <p> element's innerHTML, not to its (unsupported) value which is why it returns undefined:
document.getElementById("curr").innerHTML = currentLatLon;
So change this code:
var input = document.getElementById('curr').value;
to the following:
var input = document.getElementById('curr').innerHTML;
I just ran your web app on my end and reverse geocoding works fine after the above fix. So hope this helps!
I have the following code to display markers on a google map based upon an array of locations, however I have a mix of postcodes and Lat/longs, I've used the geocoder to convert the postcodes to lat/longs but can't then use them when I try and set a marker.
Thanks for any help!
var geocoder;
var map;
var pos;
var geoLat;
var geoLong;
var markers = [];
var bounds = new google.maps.LatLngBounds();
var locations = [
[null, 'London Eye, London', 51.503454,-0.119562, 4]
,[null, 'Palace of Westminster, London', 51.499633,-0.124755]
,[null, 'The London Dungeon', 'SE1 7PB', , 2] //Value with Postcode
];
function isNumber(o) { return ! isNaN (o-0) && o !== null && o !== "" && o !== false; }
function init() {
geocoder = new google.maps.Geocoder();
var num_markers = locations.length;
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 10,
center: new google.maps.LatLng(locations[0][2], locations[0][3]),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
for (var i = 0; i < num_markers; i++) {
if (isNumber (locations[i][2]) && isNumber (locations[i][3])){
geoLat = locations[i][2]
geoLng = locations[i][3]
alert(typeof(geoLat) +' '+typeof(geoLng)) //generates a correct number number response
}else{
geocoder.geocode( { 'address': locations[i][2]}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
geoLat = results[0].geometry.location.lat()
geoLng = results[0].geometry.location.lng()
alert(typeof(geoLat) +' '+typeof(geoLng)) //generates a correct number number response
}
});
}
pos = new google.maps.LatLng(geoLat, geoLng); // Doesn't get value if a geocodes postcode added in
bounds.extend(pos);
map.fitBounds(bounds);
markers[i] = new google.maps.Marker({
position: pos,
map: map,
id: i,
title: locations[i][1]
});
}
}
google.maps.event.addDomListener(window, 'load', init);
The Geolocation request is an async call, which means that your script is running through while the API request isn´t finished yet.
Therefore you have two options.
Define the marker directly in the callback function
if (status == google.maps.GeocoderStatus.OK) { }
Or write sth. like a setMarker() function and call it in the callback.
function setMarker(lat, lng){}
In general it is a good practice to also make the Geocoding request a function, like:
doGeocode: function (address, postal_code, callback) {
console.log("TEST: " + address.toString());
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address,
'componentRestrictions': {
'postalCode': postal_code,
'country': 'de'
}
}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
console.log(results);
callback(results);
} else {
//Error handling
alert('Geocode was not successful for the following reason: ' + status);
}
});
if you want to call it now just do
doGeocode (adress, postal_code, function (response){
//do your stuff
)};
I have created a nice Google map form that gets clients data from the database ( with a jQuery post call to php) and loads it into the clients_details. if clients_details[]['location'] which is Latlng is provided in the database all works well and marker gets displayed as expected. Problem is that when clients_details[]['location'] is not provided then I use the address from clients_details[]['address'] and try to get position of the marker by using geocoder.geocode. However surprisingly every time the code gets to the geocoder it jumps from it and comes back to it after it initialized the map ! so markers wont get added to the map !
I am assuming it has something to do with JavaScript function priorities but not sure how
<script>
var clients_details // getting this from database;
var infowindow =[];
var geocoder;
var map;
function showMarkers(clients_details)
{
var marker = [];
for (var i = 0; i < clients_details.length; i++)
{
content = 'Test Content' ;
infowindow[i] = new google.maps.InfoWindow({
content: content,
maxWidth: 350
});
var client_location;
if (clients_details[i]['location'] !== null)
{
// Geting Lat and Lng from the database string
LatLng = clients_details[i]['location'];
client_location = new google.maps.LatLng (LatLng);
}
else
{
client_address = clients_details[i]['address'];
geocoder.geocode(
{ 'address': client_address},
function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
client_location = results[0].geometry.location;
}
else
alert('Geocode was not successful for the following\n\
reason: ' + clients_details[i]['name']+'\n' + status);
});
}
marker[i] = new google.maps.Marker({
position: client_location,
map: map,
title: clients_details[i]['name']
});
// Add 'click' event listener to the marker
addListenerMarkerList(infowindow[i], map, marker[i]);
}// for
}// function
The
marker[i] = new google.maps.Marker({
position: client_location,
map: map,
title: clients_details[i]['name']
});
Code should be inside the callback in the geocoder.geocode call.
Because in your code the client_location is computed after the marker[i].
What you could do is:
compute the client_location and when the client_locolation is computed
then compute the marker[i]
So your code could be like this:
// ... your code as is
geocoder.geocode(
{ 'address': client_address},
function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
client_location = results[0].geometry.location;
// closure needed, for the marker[i] to work correctly,
// because we are in a loop on i
(function (i) {
marker[i] = new google.maps.Marker({
position: client_location,
map: map,
title: clients_details[i]['name']
});
})(i);
}
else
{
alert('Geocode was not successful for the following\n\
reason: ' + clients_details[i]['name']+'\n' + status);
}
}
);
// .... your code as is
You need to bind your call back function to the right event. Bind the initialize of the map to window load. Inside that function then call the rest of the marker/geocoder logic. As extracted from their documentation:
function initialize() {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(-25.363882, 131.044922)
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var marker = new google.maps.Marker({
position: map.getCenter(),
map: map,
title: 'Click to zoom'
});
google.maps.event.addListener(map, 'center_changed', function() {
// 3 seconds after the center of the map has changed, pan back to the
// marker.
window.setTimeout(function() {
map.panTo(marker.getPosition());
}, 3000);
});
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(8);
map.setCenter(marker.getPosition());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
I'm trying to use the Geocode API in a while loop and having no luck. It seems that my if statement inside my while loop is not evaluating until the end of the while loop. I am wondering if it is because of the Geocode API needs time to respond but I can't seem to get it to evaluate correctly. Here is my code:
while (posts != j)
{
var image = server + '/location_marker.png';
//var myLatLng = new google.maps.LatLng(locationLat[j],locationLong[j]);
var address = addressGlobal[j];
myLatLng = geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
var myLatLng = new google.maps.LatLng(lat,lng);
alert(lat + lng);
return myLatLng;
}
else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
alert(myLatLng);
place[j] = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
url: postURL[j],
title: postTitle[j]
});
google.maps.event.addListener(place[j], 'click', function() {
map.panTo(this.getPosition());
map.setZoom(7);
$("#fountainG").fadeIn(250);
history.pushState(null, this.title, this.url);
//offsetCenter(myLatLng,-400,0,map);
$(".dynamic").load(this.url + " .dynamic", function(response, status, xhr) {
$('.dynamic').fadeIn(500);
$('.dim').fadeIn(500);
$("#fountainG").fadeOut(250);
});
});
j++;
}
I think I've found the answer and it appears to be to do with closures. I'm not entirely sure how it fixed it, but I moved the geocoding functions into a nested function and then I call it within the while loop. Since it doesn't execute until the end, once it does, I need to loop through the arrays again and add them to a map. The code works successfully, but I don't really understand why, unfortunately.
I'd love if someone could chime in on why this works and perhaps a better way to set it up, but for the meantime this is fixed with:
function initialize() {
function geocode() {
var address = addressGlobal[j];
var k = 0;
myLatLng = geocoder.geocode({ 'address': address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK)
{
while (k != posts)
{
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
var myLatLng = new google.maps.LatLng(lat,lng);
alert(lat + lng);
place[k] = new google.maps.Marker({
position: myLatLng,
map: map,
icon: image,
url: postURL[k],
title: postTitle[k]
});
google.maps.event.addListener(place[k], 'click', function()
{
map.panTo(this.getPosition());
map.setZoom(7);
$("#fountainG").fadeIn(250);
history.pushState(null, this.title, this.url);
//offsetCenter(myLatLng,-400,0,map);
$(".dynamic").load(this.url + " .dynamic", function(response, status, xhr)
{
$('.dynamic').fadeIn(500);
$('.dim').fadeIn(500);
$("#fountainG").fadeOut(250);
});
});
k++;
}
}
else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
var geocoder = new google.maps.Geocoder();
google.maps.visualRefresh = true;
var mapOptions = {
zoom: 5,
center: new google.maps.LatLng(37.09024,-95.712891),
disableDefaultUI: true,
};
var posts = locationLat.length;
var j = 0;
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
var place = [];
while (posts != j)
{
var image = server + '/location_marker.png';
//var myLatLng = new google.maps.LatLng(locationLat[j],locationLong[j]);
geocode();
alert(myLatLng);
j++;
}
//Determine if the user came in via the front page or a post so we can set the viewport correctly
if ( entryPage == "post" )
{
map.setZoom(7);
var postView = new google.maps.LatLng(postLocationLat, postLocationLong);
map.panTo(postView);
}
}