I'm trying to build a little app with the Google Map API, and since it's my first javascript app (I already know about the language, but I almost never use it), I'm struggling with a little problem.
I'm trying to get the elevation related to a marker, using the ElevationService, in order to push the two datas ({marker, elevation}) into an array. However, the line where I push the datas into the array is hit before the callback function for getElevationForLocations has been called, resulting in the push of an undefined data (elevation).
I think I should use an asynchronous function in order to wait for the callback to be executed before the data has been pushed, but I don't know how to use it.
Could anyone give me indications on that ?
Thanks a lot,
Méta
P.S.: Here is my script
var markers = [];
function initMap()
{
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat: -25.363882, lng: 131.044922 },
mapTypeId: 'terrain'
});
var elevator = new google.maps.ElevationService;
map.addListener('click', function(e) {
addMarker(e.latLng, map, elevator);
});
}
function getElevation(location, elevator) {
var elevation;
// Initiate the location request
elevator.getElevationForLocations({
'locations': [location]
}, function(results, status)
{
if (status === 'OK') {
// Retrieve the first result
if (results[0]) {
return results[0].elevation;
}
}
});
}
function placeMarkerAndPanTo(latLng, map) {
var marker = new google.maps.Marker({
position: latLng,
map: map
});
map.panTo(latLng);
return marker;
//markers.push(marker);
}
function addMarker(location, map, elevator)
{ var marker = placeMarkerAndPanTo(location, map);
var elevation = getElevation(location, elevator);
markers.push({marker, elevation});
}
Here is a simplified version of your code, using what I described in my comment.
var markers = [];
var elevator = new google.maps.ElevationService;
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {
lat: -25.363882,
lng: 131.044922
},
mapTypeId: 'terrain'
});
map.addListener('click', function(e) {
addMarker(e.latLng);
});
}
function addMarker(location) {
elevator.getElevationForLocations({
'locations': [location]
}, function(results, status) {
if (status === 'OK') {
// Retrieve the first result
if (results[0]) {
var marker = new google.maps.Marker({
position: location,
map: map
});
map.panTo(location);
markers.push({
marker: marker,
elevation: results[0].elevation
});
console.log(markers);
}
}
});
}
google.maps.event.addDomListener(window, 'load', initMap);
#map {
height: 200px;
}
<script src="//maps.googleapis.com/maps/api/js"></script>
<div id="map"></div>
Edit: Seems there is a problem loading the API from the snippet at the moment (at least for me, it is crashing my browser), so here is a working JSFiddle as well.
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I am having some issues with my JavaScript in terms of properly returning a set of lat/long values from my function utilizing Google's geocoding API which takes an address and converts it into a lat,lang format which I can pass into Youtube's API to fetch a set of videos uploaded in that general vicinity.
The fix I settled upon is to create a hidden element which gets the lat long value, and then it is passed in. The following is the html tag that I settled on:
<div class="form-group" style="display:none;">
<label for="hidden">Extra:</label>
<input type="text" class="form-control" id="hidden" name="maxResults" placeholder="lat,lang">
</div>
However, my issue was that in my JavaScript, the way I originally had it, it would fail to return the value correctly. If I did an alert inside the function it would should the lat,lang values correctly. However, upon returning those values they are set as undefined for my location: Original code below:
function sendData() {
function initMap() {
var myLatLng = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng
});
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'Hello World!'
});
}
var geocoder = new google.maps.Geocoder();
// document.getElementById('submission').addEventListener('click', function() {
// geocodeAddress(geocoder, map);
// });
var myLatLng = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng
});
var keyword = $('#q').val();
console.log(geocodeAddress(geocoder,map));
var location = geocodeAddress(geocoder,map);//$('#location').val();
var r = $('#locationRadius').val();
var maxResult = $('#maxResults').val();
console.log("keyword is: " + keyword);
$.get(
"../php/geolocation.php",
{
q: keyword,
location: location,
locationRadius: r,
maxResults: maxResult
},
function (data) {
$('#geolocation-results').html(data);
}
);
}
function buttonClick() {
$("#submission").submit(function(e) {
e.preventDefault();
});
sendData();
}
function geocodeAddress(geocoder, resultsMap) {
var address = document.getElementById('location').value;
geocoder.geocode({'address': address}, function(results, status) {
if (status === 'OK') {
//resultsMap.panTo(results[0].geometry.location);
var marker = new google.maps.Marker({
map: resultsMap,
position: results[0].geometry.location
});
var lat = results[0].geometry.location.lat();
var latS = toString(lat);
var lng = results[0].geometry.location.lng();
var lngS = toString(lng);
var latlngS = latS.concat(",",lngS);
var latlng = new google.maps.LatLng(lat, lng);
resultsMap.setCenter(latlng);
console.log(latlngS);
return latlngS;
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
And below is the fix I settled upon
function geocode() {
var myLatLng = {lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng
});
var geocoder = new google.maps.Geocoder();
geocodeAddress(geocoder, map);
}
function sendData() {
// document.getElementById('submission').addEventListener('click', function() {
// geocodeAddress(geocoder, map);
// });
var keyword = $("#q").val();
var r = $('#locationRadius').val();
var maxResult = $('#maxResults').val();
var location = $("#hidden").val();
console.log("keyword is: " + keyword);
$.get(
"../php/geolocation.php",
{
q: keyword,
location: location,
locationRadius: r,
maxResults: maxResult
},
function (data) {
$('#geolocation-results').html(data);
}
);
}
function buttonClick() {
$("#submission").submit(function(e) {
e.preventDefault();
});
sendData();
}
function geocodeAddress(geocoder, resultsMap) {
var address = document.getElementById('location').value;
geocoder.geocode({'address': address}, function (results, status) {
if (status === 'OK') {
resultsMap.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: resultsMap,
position: results[0].geometry.location
});
var latS = results[0].geometry.location.lat().toString();
var lngS = results[0].geometry.location.lng().toString();
//alert((results[0].geometry.location.lat()));
var latLang = latS.concat(',', lngS);
$('#hidden').val(latLang);
console.log($('#hidden').val());
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
The geocode function is called via an onblur in my html:
<div class="form-group">
<label for="location">location</label>
<input type="text" class="form-control" id="location" name="location" placeholder="Athens, GA" onblur="geocode()">
</div>
So really, to wrap up a rather lengthy code, I want to know how I can avoid having to maintain this disgusting fix in terms of having a hidden in-between form element? Apologies if this is a poorly worded question, I tried my best.
If you want sendData() to be called automatically with the location data as soon as the latLang in geocode's callback is available, then you could:
add a parameter to the function definition as in function sendData(location) and remove the var location = ... initialization and the hidden element because location will instead be set as a parameter to sendData;
and
call sendData(latlang) in geocode's anonymous function callback instead of setting the hidden value, on the line where you are currently setting hidden.
The idea is to create a function that can be called in the geocode callback
and consume its latlang data there instead of storing it globally.
Alternatively, you could set a global variable in a callback instead of the value of a hidden element, but then you can't use it until it is defined. That's no good for automatically chaining the steps, but might be ok if a human watches and pushes a button for the next step. Like the usage of hidden element values, it can lead to synchronization issues.
In gmap3 google maps library, I am trying to make a function that makes a marker with an infowindow.
http://gmap3.net/api-infowindow.html
function addMarker(map, marker, content) {
map.marker(marker)
.infowindow({
'content' : content
})
.then(function (infowindow) {
var map = this.get(0);
var marker = this.get(1); // <---- this gets the first marker on both times I call addMarker, i.e. uluru
marker.addListener('click', function(event, data) {
infowindow.open(map, this);
});
});
}
$(document).ready(function() {
var uluru = {lat: -25.363, lng: 131.044};
var map = $('#map')
.gmap3({
zoom: 4,
center: uluru
});
addMarker(map, {
position: uluru
}, "text");
addMarker(map, {
position: {lat: 48.8620722, lng: 2.352047}
}, "text2");
});
This is what I have, but the problem is, in the top, where I try to get a marker (i put a comment in the code), it seems to be referencing the wrong marker. Both times I call it, it references the first marker I make. As a result, if I click the first marker on the map, I get both infowindows showing up on that marker.
Does anyone know whats wrong?
Thanks
The "get" function retrieves the chained results from the beginning, indexes will never change.
Store it locally in your function using the "then"
function addMarker(map, marker, content) {
var gmMarker;
map
.marker(marker)
.then(function (m) {
gmMarker = m;
})
.infowindow({
'content' : content
})
.then(function (infowindow) {
var map = this.get(0);
gmMarker.addListener('click', function(event, data) {
infowindow.open(map, this);
});
});
}
In my project I have a google map, and I need to get markers on my map from database.
I have simple code like in example:
var geocoder;
var map;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 8,
center: latlng
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
google.maps.event.addListener(map, 'idle', function () {
getmarkers(map);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
This code works well, but it has one lack - it loads new markers only if user moves map.
But I need to load markers also if user is just sitting in front of computer and look on a map, not moving it.
I think the best way to do this is to use setInterval(getmarkers(map), 3000) but if I use it except where that function google.maps.event.addListener(... it can't find map. Are there any ways to solve this problem?
there are 2 issues,
setInterval expects the first argument to be a function(but it isn't, it's a function-call which will be executed immediately). Use a anonymous function to execute the statement:
setInterval(function(){getmarkers(map);}, 3000);
place the setInterval-call at the end of initialize to be sure that map is defined.
My javascript isn't too hot, I'm trying to add a manual marker onto a number of locations gathered from the Google Places API.
I followed this post to get to my following code (with a few amendments):
<script type="text/javascript">
var map;
var infowindow;
var service ;
base_Icon_festival = "https://maps.gstatic.com/mapfiles/ms2/micons/volcano.png";
shadow_festival = "https://maps.gstatic.com/mapfiles/ms2/micons/volcano.shadow.png";
function initialize(lat,lng)
{
var origin = new google.maps.LatLng(lat,lng);
map = new google.maps.Map(document.getElementById('map'), {
mapTypeId: google.maps.MapTypeId.HYBRID,
center: origin,
zoom: 14,
scrollwheel: false,
});
var request = {
location: origin,
radius: 2500,
types: ['train_station','bus_station','subway_station','airport']
};
infowindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
service.search(request, callback);
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
base_Icon_train = "http://maps.google.com/mapfiles/ms/icons/red-dot.png";
base_Icon_bus = "http://maps.google.com/mapfiles/ms/icons/green-dot.png";
base_Icon_subway = "http://maps.google.com/mapfiles/ms/icons/blue-dot.png";
base_Icon_airport = "http://maps.google.com/mapfiles/ms/icons/yellow.png";
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker;
var icon_to_use;
if (place.types.indexOf('train_station') != -1) {
icon_to_use = base_Icon_train;
} else if (place.types.indexOf('bus_station') != -1) {
icon_to_use = base_Icon_bus;
} else if (place.types.indexOf('subway_station') != -1) {
icon_to_use = base_Icon_subway;
} else if (place.types.indexOf('airport') != -1) {
icon_to_use = base_Icon_airport;
}
marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: icon_to_use
});
var content='<strong style="font-size:1.2em">'+place.name+'</strong>'+
'<br/><strong>Latitude: </strong>'+placeLoc.lat()+
'<br/><strong>Longitude: </strong>'+placeLoc.lng()+
'<br/><strong>Type: </strong>'+place.types[0];
//make a request for further details
service.getDetails({reference:place.reference}, function (place, status)
{
if (status == google.maps.places.PlacesServiceStatus.OK)
{
more_content='<hr/><strong>Details';
if(place.website)
{
more_content+='<br/><br/><strong>'+place.website+'';
}
}
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(content+more_content);
infowindow.open(map, this);
});
}
google.maps.event.addDomListener(window, 'load', function(){initialize(<?php echo $coordinated; ?>);});
</script>
<div id="map" style="height:400px;"></div>
Now I would like to manually add another marker which is located at the center of the map (ie, the variable origin which is currently being pulled from a PHP variable - var origin = new google.maps.LatLng(lat,lng);). I also need this marker to have a different icon associated with it (base_Icon_festival and shadow_festival respectively).
I'm not sure how to manually add another marker to the ones already gathered by the places API?
End goal: have a festival icon marker at the center of the map and a number of public transport markers surrounding it, resulting code to go on individual festival pages of a website.
Thanks in advance to anyone who can help.
In the Google Maps API, markers are added to the map by creating a Marker object and setting the map property. This is the snippet in your code that adds the existing Markers.
marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: icon_to_use
});
To add a new marker you would just replace the position and icon properties with your values.
new google.maps.Marker({
map: map,
position: origin,
icon: shadow_festival
});
This code can probably be added at the end of the Callback function and if you don't need the actual marker object for anything else, you can just create the Marker object and never assign it.
There is an example from the Google Maps API docs here.
var MapApiApplication = {
myCurrentPosition : "",
mapOptions : "",
marker : "",
initialize : function(){
MapApiApplication.myCurrentPosition = new google.maps.LatLng(10.112293000000000000, 76.352684500000010000);
MapApiApplication.mapOptions = {
zoom: 13,
center: MapApiApplication.myCurrentPosition,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
MapApiApplication.map = new google.maps.Map(document.getElementById('map-canvas'), MapApiApplication.mapOptions);
MapApiApplication.marker = new google.maps.Marker({
position: MapApiApplication.myCurrentPosition,
map: MapApiApplication.map,
title: 'Here You are'
});
},
};
I have the current position's latitude and longitude. How can i find nearby hospitals locations using only javascript and google maps api.
You need to use the Places Library. In the Place Search Requests you can specify a type - which categorizes what "type" of place you are searching for. According to the Supported Place Types by Google Places API, there are hospital and health types - which would probably be your best bet to get hospitals in your search response.
I had a chance to work on it recently.
Here is the working code snippet:
// comments inline
var map;
var infowindow;
function initialize() {
var pyrmont = new google.maps.LatLng(19.107567, 72.8335); // sample location to start with: Mumbai, India
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: pyrmont,
zoom: 15
});
var request = {
location: pyrmont,
radius: 200,
types: ['hospital', 'health'] // this is where you set the map to get the hospitals and health related places
};
infowindow = new google.maps.InfoWindow();
var 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++) {
createMarker(results[i]);
}
}
}
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);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<div id="map-canvas"></div>
It is important to note that the places wouldnt be marked onto the map if you load the library and Javascript at the end of <body> tag.
actually i require an api to find hospitals near me.the thing is i require it for thunkable.Can u tell me how to use the above api(https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places) for the same