Convert latitude, longitude in to address as a string - javascript

Please help me resolve this problem.
I want to get address from latitude, longitude in Google Maps.
Here is my functions:
function codeLatLng() {
var geocoder = new google.maps.Geocoder();
var lati = document.getElementById("latitude_value").value;
var lngi = document.getElementById("longitude_value").value;
var latlng = new google.maps.LatLng(lati, lngi);
var infowindow = new google.maps.InfoWindow();
var ngo;
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(11);
marker = new google.maps.Marker({
position: latlng,
map: map
});
ngo = results[1].formatted_address;
infowindow.setContent(results[1].formatted_address);
infowindow.open(map, marker);
}
} else {
alert("Geocoder failed due to: " + status);
}
});
return ngo;
}
When this function is executed. The address is displayed in Maps.
However, this is not what I need. I just want to assign this address to variable 'ngo' as a string.
This function return 'ngo' which is displayed in the text field as 'undefinded'.
I need some help to solved this problem.
Thanks.

I just want to assign this address to variable 'ngo' as a string.
That's the problem right there. You can't do that. JavaScript just doesn't work that way. The geocoder call is asynchronous. It returns before the data is received from the server. The data isn't ready until the geocoder callback function is called.
What you need to do instead is to use that ngo data in the callback function itself, or call another function and pass it the data, and use the data there.
For example, where you have this line:
ngo = results[1].formatted_address;
you can replace it with:
useNGO( results[1].formatted_address );
where useNGO is a function you've defined (anywhere) like this:
function useNGO( ngo ) {
// Do stuff with ngo here
}

I believe your problem is that using the var keyword when declaring var ngo makes ngo a local variable, so it doesn't exist outside of codeLatLng(). Try deleting var ngo, placing ngo = ""; somewhere outside of any function declarations (like right before function codeLatLng() {), and let me know if that works :)

Related

Can't get Googlemaps Geocoder to return LatLng with callback

Can someone look at my code and tell me what I'm doing wrong? I understand that the Googlemaps geocoder is an async function so there needs to be a callback to handle the results. So I'm following the example here but I still can't get it to work:
How do I return a variable from Google Maps JavaScript geocoder callback?
I want to give my codeAddress function an actual address and a callback function. If the results array has something I send the lat and lng to the callback function.
codeAddress = function(address, callback) {
var gpsPosition = {};
if (geocoder) {
geocoder.geocode({'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
console.log("got results!");
var lat = results[0].geometry.location['B'];
var lng = results[0].geometry.location['k'];
callback(lat, lng);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
};
This is the callback function. Basically it takes the lat and lng from the codeAddress function and puts the lat and lng into a hash and returns it. The idea is to then store the hash into a variable called location and reference location when I'm creating a new map marker.
createGPSPosition = function(lat, lng){
console.log("createGPSPosition called with lat and lng:");
console.log(lat);
console.log(lng);
var gpsPosition = {};
gpsPosition.B = lat;
gpsPosition.k = lng;
console.log("gpsPosition:");
console.log(gpsPosition);
return gpsPosition;
};
When I run this code console.log(gpsPosition); actually logs the final hash object. But I still don't see the object getting returned... so when I do:
var stuff = codeAddress("1600 Amphitheatre Pkwy, Mountain View, CA 94043", createGPSPosition)
stuff still turns up as undefined. What's going on here?
This problem is that you're expecting asynchronous code to work in a synchronous way. stuff is defined before codeAddress finishes searching. The simplest solution is to provide a different callback, define stuff within that and use it there. This should work fine:
codeAddress("1600 Amphitheatre Pkwy, Mountain View, CA 94043", function(lat, lng){
var stuff = createGPSPosition(lat, lng);
console.log(stuff); // => your gpsPosition object
});
An alternative would be to learn Promises.

Return value with google maps geocoder [duplicate]

This question already has answers here:
How do I return a variable from Google Maps JavaScript geocoder callback?
(5 answers)
Closed 9 years ago.
I just can't find what's wrong with this bit of code:
function getLocationName(latitude, longitude) {
if (isNaN(parseFloat(latitude)) || isNaN(parseFloat(longitude))) {
return false;
}
var locationName;
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude, longitude)
// Reverse Geocoding using google maps api.
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
locationName = results[1].formatted_address;
alert(locationName);
}
else {
locationName = "Unknown";
}
}
else {
locationName = "Couldn't find location. Error code: " + status;
}
});
alert(locationName);
return locationName;
}
I call this from a jquery event handler like this:
$("#id").on("event", function (event, ui) {
$("#userLocation").text(getLocationName(latitude, longitude));
});
Weird part is that the first alert gets the correct value of 'locationName' but the second one always returns 'undefined'. I tried initializing the variable with a value and in that case the first alert again returned the correct location name but the second one returned the initialization value. This gives me a notion that this might be a variable scope related problem but I just can't figure what.
PS. I don't have any other variables (local/global) by the same name.
Update: The alert works fine now (thanks to Lwyrn's answer) but the return value is still wrong. I've followed the answers in the linked SO question and still I couldn't 'return' the right value. The alert did work fine.
You have to move "alert(locationName);" into the geocoder.geocode callback. Because geocoder.geocode executes an AJAX request. When you throw the alert the var locationName is still undefined (not set).
Try it like this
function getLocationName(latitude, longitude, callback) {
if (isNaN(parseFloat(latitude)) || isNaN(parseFloat(longitude))) {
return false;
}
var locationName;
var geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(latitude, longitude)
// Reverse Geocoding using google maps api.
geocoder.geocode({ 'latLng': latlng }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
locationName = results[1].formatted_address;
alert(locationName);
}
else {
locationName = "Unknown";
}
}
else {
locationName = "Couldn't find location. Error code: " + status;
}
alert(locationName);
callback(locationName);
});
}
To get the "return" you have to create a your own callback.
Try like this
$("#id").on("event", function (event, ui) {
getLocationName(latitude, longitude, function(result){
$("#userLocation").text(result);
});
});
As for the alert, the return is called before the ajax request. So you have to use a callback to be called when the ajax request has done his job!

better approach then setTimeout on Google Map V3

in my Asp.net Web Application where i am using the setTimeout to Get rid of
geocoder OVER_QUERY_LIMIT, the shorter time out is 10ms which is too longer for me, I have 800 above addresses coming from SQL SERVER which would be increased because of this setTimeout will take about 5 to 7 mints to take places of all the markers on map and that`s frustrating. I researched and saw this link setTimeout: how to get the shortest delay
but cant figure out what he want to do actually. please someone guide me....
function InitializeMap() {
// Here am calling the webService by PageMethods in which CityNames, Countries Name will take their places
PageMethods.GetCitiesbyUser_Extender(onSucess);
var myOptions =
{
zoom: 0,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
var map = new google.maps.Map(document.getElementById("map"), myOptions);
// Creating latlngbound to bound the markers on map
var bounds = new google.maps.LatLngBounds();
//// Creating an array that will contain the addresses
var places = [];
// Creating a variable that will hold the InfoWindow object
var infowindow;
// create this to add the marker Cluster on map
mc = new MarkerClusterer(map);
var popup_content = [];
var geocoder = new google.maps.Geocoder();
// image for ballon i want to change default ballon to this
var iconimage = "http://chart.apis.google.com/chart?cht=mm&chs=24x32&chco=FFFFFF,008CFF,000000&ext=.png";
var markers = [];
// Create this function for passing the values which was taken by webservice cntName is the return in webservice
function onSucess(cntName){
// loop through the cntName to pass the individual City one by one from geocode
for (i = 0; i < cntName.length; ++i) {
//for fixing the issue use closure to localize the cntName[i] variable before passing into geocode and callback function within it.
(function CreateMarkAndInfo(address) {
geocoder.geocode({ 'address': address },
function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
places[i] = results[0].geometry.location;
var marker = new google.maps.Marker({
position: places[i],
title: results[0].formatted_address,
map: map,
icon: iconimage
});
markers.push(marker);
mc.addMarker(marker);
google.maps.event.addListener(marker, 'click', function () {
if (!infowindow) {
infowindow = new google.maps.InfoWindow();
}
// Setting the content of the InfoWindow afterward
infowindow.setContent(popup_content[i]);
// Tying the InfoWindow to the marker afterward
infowindow.open(map, marker);
});
// Extending the bounds object with each LatLng
bounds.extend(places[i]);
// Adjusting the map to new bounding box
map.fitBounds(bounds);
// Zoom out after fitBound
var listener = google.maps.event.addListenerOnce(map, "idle", function () {
if (map.getZoom() < 10) map.setZoom(2);
});
}
else {
// if geocode will end the limit then make delay by timer in order to avoid the OVER_QUERY_LIMIT
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function () { CreateMarkAndInfo(address); }, (15)); // here i think i should use better approch but for now it`s ok.
}
else {
alert("Geocode was not successful for the following reason: " + status);
}
}
});
})(cntName[i]);// End closure trick
}
}
}
google.maps.event.addDomListener(window, 'load', InitializeMap);
Edit:
#just.another.programmer i cant because there is no latitute and longitude in DB, client will add cities and countries by him self thats why i had to convet city and country names by geocode and geocode doing it`s job accuretly here
How i am calling the City and country Names by web service
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod()]
public static string[] GetCitiesbyUser_Extender()
{
System.Data.DataSet dtst = new System.Data.DataSet();
string ses = HttpContext.Current.Session["UserName"].ToString();
USTER.Dal.clsSearch clssearch = new USTER.Dal.clsSearch();
// Assinging the Stroed Procedure Method to DataSet
dtst = clssearch.GetAllCitiesByUser(ses);
string[] cntName = new string[dtst.Tables[0].Rows.Count];
int i = 0;
try
{
foreach (System.Data.DataRow rdr in dtst.Tables[0].Rows)
{
// Columns Name in SQL Server Table "CityName" and "CountryName"
cntName.SetValue(rdr["CityName"].ToString() +","+ rdr["CountryName"].ToString() , i);
i++;
}
}
catch { }
finally
{
}
return cntName;
}
Geocode your addresses one time when you first get them, then store the lat/long in your db so you don't have to geocode again. This will dramatically reduce your geocode requests and remove the need for setTimeout.

google maps geocoding and order of initialization

so I've run into a problem recently, and maybe you guys can help.
So to start off, I've created website and a marker, and I'm trying to retrieve the center point to reverse-geocode the address.
My code is below :
function ReverseGeocode(lat, lng)
{
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({"latLng": latlng}, function(results, status)
{
if (status != google.maps.GeocoderStatus.OK)
{
alert("Geocoding has failed due to "+ status);
}
address = results[0].formatted_address;
});
}
The problem I'm having here, is when I try to pass "address" back out (address is right now a global variable) all I get is "undefined".
Here's the code where I'm trying to pass it back out:
sendString += '&lat=' + lat;
sendString += '&lng=' + lon;
ReverseGeocode(center.lat(), center.lng());
alert(""+address);
sendString += '&address=' + address
var currentLang = "en"
sendString += '&phone=' + document.getElementById("number").value;
sendString += '&email=' + document.getElementById("email").value;
sendString += ($("prefsms").checked)?'&contactMethod=sms':'&contactMethod=email';
sendString += '&serviceType=' + document.getElementById("serviceType").value;
sendString += '&language=' + currentLang;
alert(""+sendString);
In my alert box, all I get is "undefined". Yet, if I add another alert box INTO the ReverseGeocode function, I'll get the address in an alert box, but this occurs AFTER the alert box in the outside function.
Any ideas as to what's going on? I would have thought that the alert box inside the ReverseGeocode function would go first, not the other way around.
Thanks!
As Heitor Chang said, Geocoding is asynchronous - so when you try to return the address, it get's returned to the function you pass as a callback to geocoder.geocode(). Confused? see this:
function ReverseGeocode(lat, lng)
{
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({"latLng": latlng}, function(results, status)
{
if (status != google.maps.GeocoderStatus.OK)
{
alert("Geocoding has failed due to "+ status);
}
return results[0].formatted_address; // this is how you might've been returning (i am just assuming since you didn't provide any code that returns address.
});
}
Now you can see that it gets returned to the function you are passing to geocoder.geocode()
What you should be doing is use callbacks - you are passing one here, probably without realising it - accept a callback as the third argument to ReverseGeocode function and when you get the result as OK, call the callback and return the address. Here's how:
function ReverseGeocode(lat, lng, cb) // cb - callback, a function that takes the address as an argument.
{
var latlng = new google.maps.LatLng(lat, lng);
var geocoder = new google.maps.Geocoder();
geocoder.geocode({"latLng": latlng}, function(results, status)
{
if (status != google.maps.GeocoderStatus.OK)
{
alert("Geocoding has failed due to "+ status);
}
cb(results[0].formatted_address); // call the callback passing to it the address and we're done.
});
}
How to use it? This way:
ReverseGeocode( LAT, LNG, function(address) {
// do something with the address here. This will be called as soon as google returns the address.
});
(Reverse) Geocoding is asynchronous, meaning the request goes to Google servers, your script keeps running, and the code inside result is OK block executes when Google sends back its reply. The overall execution won't necessarily follow the order of commands in the order it was written.
To use the value of address your code has to be included in that code block where the status returned is OK.

google maps JavaScript issues

First off thank you in advance for taking time to help me with this, I appreciate your efforts.
I have a problem with google maps api, JavaScript version 3.
I have written the following code
$('.adr').ready(function(){
initialize();
})
function initialize() {
var myLatlng = codeAddress();
var myOptions = {
zoom: 14,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.SATELLITE
};
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
}
function codeAddress()
{
var geocoder = new google.maps.Geocoder();
var address;
var street = cropAdr($(".street-address").text());
var city = cropAdr($(".locality").text());
var state = cropAdr($(".region").text());
var zip = cropAdr($(".zip").text());
address = street + ", " + city + ", " + state + ", " + zip;
geocoder.geocode( {'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var latlng = results[0].geometry.location;
return latlng;
}
else
{
alert("Geocode was not successful for the following reason: " + status);
return null;
}
});
}
function cropAdr(args)
{
var index = args.indexOf(":");
var value = args.substr(index+1);
return value;
}
But it doesn't work.
I have checked the value of the "results[0].geometry.location" return and its perfect, so the address manipulation works. The "results[0].geometry.location" is a google.maps.Latlng object, but I have tried to strip out just the co-ords as strings, then create a new google.maps.Latlng object but no dice.
yet if I manually copy that string and paste the value into "var myLatlng = new google.maps.Latlng(Paste Copied String here!)" the whole thing works!!
I cannot see what else is wrong this script (apologies for the jumble of Jquery and Javascritpt).
The Google Maps API Geocoder accepts a function that will be run when the address has been geocoded, but that function may be called asynchronously - that is, after the rest of your code has already finished running.
In codeAddress you call the Geocoder and pass in a function with this line:
geocoder.geocode( {'address': address}, function(results, status)
You then try and return a latLng from the function passed to the geocoder, but that is not the same as returning a value from codeAddress. The value you return from inside this function will be passed to the geocoder object, which will just ignore it.
You need to have the function you pass to geocode do something with the latLng. For example, replace:
return latLng;
with:
map.setCenter(latLng);
And the map should center itself on the geocoded address once the result is available.
(To do this you will need to make the map object global or otherwise make it available to codeAddress. I suggest adding "var map;" at the top of your code, and remove "var" from in front of the use of map in initialize)

Categories