I have a serious problem that i have been trying to debug for a few days already.
I have a script that gets users current latitude and longitude, and then stores them in variables. however, when i try to use these variables outside this function and in the //init map zone, the map is just not showing up. by alerting out the variables i can see that outside the position function variables are set to "Undefined". here is my code:
//main function here
function initialize() {
var lat;
var lon;
//check if user has geo feature
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(
//get position
function(position){
lat = position.coords.latitude;
lon = position.coords.longitude;
},
// if there was an error
function(error){
alert('ouch');
});
}
//case the users browser doesn't support geolocations
else {
alert("Your browser doesn't support geolocations, please consider downloading Google Chrome");
}
//init map
var myOptions = {
center: new google.maps.LatLng(lat, lon),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
}
Thanks for any help, Ariel
That is because you declare your variables within the function. The variables gets private to the initialize function and can only be accessed from within it. If you need to be able to access your variables outside of the initialize function, then move the variable declaration out of the function.
var lat;
var lon;
function initialize() {
...
Have a look at this MDN article about variable scope in JavaScript.
UPDATE
Looking through the code again I realize that the problem isn't variable scope, got confused by the indentation. I'm not familiar with the Geolocation API but I believe that the problem might be that the navigator.geolocation.getCurrentPosition() is asynchronous, as it will have to wait for the user to allow the website to get the position of the device. Therefor myOptions will have been assigned before the actual position have been retrieved - thus lat & lng are still undefined when myOptions is assigned.
Try this instead:
//main function here
function initialize() {
var lat, lon, map, myOptions;
//check if user has geo feature
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(
//get position
function(position){
lat = position.coords.latitude;
lon = position.coords.longitude;
//init map
myOptions = {
center: new google.maps.LatLng(lat, lon),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
},
// if there was an error
function(error){
alert('ouch');
});
}
//case the users browser doesn't support geolocations
else {
alert("Your browser doesn't support geolocations, please consider downloading Google Chrome");
}
}
More of a correction on the other answer. The issue of scope is not relevant. As defined in the original code lat and lon are in scope in the context to which the question author is using alert.
Here's a runnable example that proves it.
function getPos( f ) {
var position = new Object();
position.coords = new Object();
position.coords.latitude = 5;
position.coords.longitude = 10;
f( position );
}
function initialize() {
var lat;
var lon;
getPos(
function(position){
lat = position.coords.latitude;
lon = position.coords.longitude;
}
);
alert( lat + " " + lon );
}
initialize(); //expected 5 & 10
Anyways, this doesn't seem to be a pure JS issue. This seems to be an issue with whatever google api you are using. This question should have been tagged with such, as I have no knowledge of this API or whether you're calling it wrong or not.
Related
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.
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 :)
I thought I understood how the default operand worked in JavaScript, but clearly not. I'm trying to first determine the user's geographic position, and load a map centered on those coordinates. If the device is unable to determine those coordinates, it would fallback to just loading the map with some default values.
You'll notice that in my error method, I'm calling gMap.init() with no arguments, which I thought should mean that the variables lat and lon should be set to 57.700992 and 11.893836 respectively. Instead, I'm getting Uncaught TypeError: Cannot read property 'coords' of undefined. Where am I going wrong?
Also, in theApp.init() I'm calling the map if navigator.geolocation exists. Does that mean browsers that don't support HTML5 geolocation will not even try loading the map?
var gMap = {
init: function (position) {
var lat = position.coords.latitude || 57.700992,
lon = position.coords.longitude || 11.893836,
geocoder = new google.maps.Geocoder(),
mapOptions = {
zoom: 12,
center: new google.maps.LatLng(lat, lon)
},
map = new google.maps.Map(document.getElementById('mapcanvas'), mapOptions);
},
error: function () {
console.log('failed to retrieve geoposition');
gMap.init();
}
}
var theApp = {
init: function () {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(gMap.init, gMap.error, {timeout:10000});
}
}
}
The || you have there should work, unless position.coords or position is undefined. In that case, JavaScript will throw a error because you're trying to access a property on a undefined object.
You will have to manually check if the objects exist:
var lat, lon;
if(position && position.coords){
lat = position.coords.latitude || 57.700992;
lon = position.coords.longitude || 11.893836;
}
If position is undefined, the if will abort, without trying to check for position.coords.
(The && doesn't evaluate the right parameter, if the left one is false)
And yes, if navigator.geolocation is undefined, the map will not be loaded:
navigator.geolocation.getCurrentPosition(gMap.init, gMap.error, {timeout:10000});
This ^ will not be executed, so gMap.init will not be executed.
You should try
var lat = position.coords.latitude ? window['position'] != undefined : 57.700992,
lon = position.coords.longitude ? window['position'] != undefined : 11.893836,
instead of ||
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.
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)