Prohibit looping functions - javascript

Function onSuccess runs indefinitely, as constantly asks the coordinates from the GPS receiver. It contains a function createMap, to be performed only once. How is this achieved? Make a function outside the function also can not, because it is passed as a parameter value of a variable of the function.
watchID = navigator.geolocation.watchPosition(function(position) {onSuccess(position, arrMyLatLng);}, onError, options);
function onSuccess(position, arrMyLatLng)
{
var latitude , longitude ;
latitude = position.coords.latitude ;
longitude = position.coords.longitude;
var myLatLng = new google.maps.LatLng(latitude, longitude);
createMap(myLatLng, arrMyLatLng);// This feature will run for an indefinite number of times. It is only necessary once.
map.panTo(myLatLng) ;
}

You can create a function with private state using a closure:
onSuccess = (function() {
var created = false;
return function (position, arrMyLatLng) {
var latitude , longitude ;
latitude = position.coords.latitude ;
longitude = position.coords.longitude;
var myLatLng = new google.maps.LatLng(latitude, longitude);
if (!created) {
createMap(myLatLng, arrMyLatLng);
created = true;
}
map.panTo(myLatLng) ;
};
}());

Function that runs only once:
function runOnce() {
if (runOnce.done) {
return;
} else {
// do my code ...
runOnce.done = true;
}
}
Because function is object in JavaScript, you may set a property on it.

Assuming createMap returns a map
var map = null;
function onSuccess(position, arrMyLatLng) {
var latitude = position.coords.latitude ;
var longitude = position.coords.longitude;
var myLatLng = new google.maps.LatLng(latitude, longitude);
map = map || createMap(myLatLng, arrMyLatLng);
map.panTo(myLatLng);
}
createMap will only run if map evaluates to "false" (i.e. is null), thus createMap only runs once.

Related

Variable overwritten by ajax response

Using Google Maps and the Geocoder, I'm trying to loop over an object of addresses, return LatLng addresses for them, and create markers using both the original details and the latlng address in the setMarker function below.
The problem is, the response[a] is being overwritten by the last address in the object, because the for loop is running ahead of the AJAX results being returned.
How can I save the data in the current response[a] being looped over, so that when setMarker() is later called, it contains the right information?
Thanks
var limit = 0;
for (a in response){
if(limit<5){ // limit API calls
var addr = [response[a].Addr1, response[a].City, response[a].Zip];
geo = new google.maps.Geocoder();
geo.geocode({
address: addr.join(", "),
componentRestrictions: {
// country: 'UK'
}
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK && results) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var latlng = new google.maps.LatLng(latitude, longitude);
if(latitude!="" && longitude!=""){
bounds.extend(latlng);
map.fitBounds(bounds);
_this.setMarker(map, limit, latlng, response[a]);
}
} // if geo results
});
}
limit++;
}
The problem you are facing is a classic one that can be solved using closure function.
Current code looks something like :
var a[20];
for(i=0;i<20;i++) {
some_async_method() {
//code that uses 'a[i]'
}
}
Using closure to preserve the scope of var a inside a async function :
var a[20];
for(i=0;i<20;i++) {
(function(_a){
some_async_method() {
//code that uses 'a[i]' as '_a'
}
})(a[i]);// self calling function that preserves the scope of a[i]
}
So your code will look like :
var limit = 0;
for (a in response){
if(limit<5){ // limit API calls
var addr = [response[a].Addr1, response[a].City, response[a].Zip];
geo = new google.maps.Geocoder();
(function(response_a){ // closure function to preserve scope of 'response[a]'
geo.geocode({
address: addr.join(", "),
componentRestrictions: {
// country: 'UK'
}
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK && results) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
var latlng = new google.maps.LatLng(latitude, longitude);
if(latitude!="" && longitude!=""){
bounds.extend(latlng);
map.fitBounds(bounds);
_this.setMarker(map, limit, latlng, response_a);
}
} // if geo results
});
})(response[a]);
}
limit++;
}

How to run success function with JQuery getJSON?

I want to push data to an array, but am unsure how to go about this due to AJAX's asychronisity.
I can't seem to find complete examples online of the way this is done with getJSON.
I've been following the documentation here with no luck/
I have tried:
var jsonLtdLng="https://maps.googleapis.com/maps/api/geocode/json?address=" + addressval;
var latlng;
$.getJSON(jsonLtdLng, function (data) {
var lat = data.results[0].geometry.location.lat;
var lng = data.results[0].geometry.location.lng;
latlng = {lat: lat, lng: lng};
}).done(function() {
markerlocations.push(latlng);
})//END JSON
and:
var jsonLtdLng="https://maps.googleapis.com/maps/api/geocode/json?address=" + addressval;
var latlng;
$.getJSON(jsonLtdLng, function (data) {
var lat = data.results[0].geometry.location.lat;
var lng = data.results[0].geometry.location.lng;
latlng = {lat: lat, lng: lng};
markerlocations.push(latlng);
});
and variations of this with no results.
Would anyone know the correct way of doing this and can point me in the right direction?
You need to push() to the array in the success handler which has access to the data returned from the request. You would also be better to add objects to the array instead of manually hacking around a JSON string. From there you can pass the array to whatever function you need to execute. Try this:
var markerlocations = [];
$.getJSON(jsonLtdLng, function (data) {
var lat = data.results[0].geometry.location.lat; // note 'lat' here, not 'lng'
var lng = data.results[0].geometry.location.lng;
markerlocations.push({ lat: lat, lng: lng });
doSomethingWithTheArray(markerlocations);
});
function doSomethingWithTheArray(arr) {
for (var i = 0; i < arr.length; i++) {
console.log(arr[i].lat, arr[i].lng);
}
}
Try this. Use foreach to create your array. Then push/append the array as you want.
$.getJSON("url here", function(data) {
$.each(data, function(key, value){
// your custom code here
var latlng = 'code you want';
});
markerlocations.push(latlng);
});
You need to declare an empty array outside getJSON() function. Then it is accessible inside getJSON callback.
var markerlocations = [];
$.getJSON(jsonLtdLng, function (data) {
var lat = data.results[0].geometry.location.lat;
var lng = data.results[0].geometry.location.lng;
markerlocations.push({ lat: lat, lng: lng });
});
function(data)... is the callback function which gets executed once the response is obtained. You don't need another done() method in this case.
var jsonLtdLng="https://maps.googleapis.com/maps/api/geocode/json?address=new york";
var latlng;
var markerlocations = [];
$.getJSON(jsonLtdLng, function (data) {
var lat = data.results[0].geometry.location.lat;
var lng = data.results[0].geometry.location.lng;
latlng = {lat: lat, lng: lng};
markerlocations.push(latlng);
// just for testing
for(var i = 0; i < markerlocations.length; i++){
alert(markerlocations[i].lat + '===' + markerlocations[i].lng);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Not able to display Google map

This is javascript function to access latitude longitude and city from json:
function parse()
{
var json = '<?php echo $json; ?>';
var events = jQuery.parseJSON(json);
var DateArray = new Array();
var size = Object.keys(events).length;
search(events);
}
function search(events)
{
for ( i in events)
{
if( typeof events[i] === 'object' )
{
key= i.toLowerCase();
if(key.indexOf("latitude") !== -1)
{
var lat = events[i];
var longi = events['longitude'];
// alert(lat + longi);
initialize(lat,longi,'5');
// DateArray = DateArray.concat(events[i]);
// alert('DataArray');
}
search(events[i]);
}
}
}
I have this json:
{
"type":"http://schema.org/Place",
"class":"place",
"city":"London",
"geo":{
"type":"http://schema.org/GeoCoordinates",
"class":"geocoordinates",
"latitude":"30",
"longitude":"70"
}
}
map code:
function initialize(a,b,zom){
if (!a || !b ||!zom){
var centerLoc=new google.maps.LatLng( 34.61701054652337,71.37824736488983);
zoom=16;
}
else
{
alert(typeof a + typeof b + typeof zom);
var zoom =parseInt(zom);
var centerLoc=new google.maps.LatLng(a,b);
alert('it works fine');
}
var mapProp = {
center:centerLoc,
zoom:zoom,
//mapTypeId:google.maps.MapTypeId.ROADMAP
mapTypeId:google.maps.MapTypeId.SATELLITE
};
var map=new google.maps.Map(document.getElementById("googleMap") ,mapProp);
marker=new google.maps.Marker({
position:centerLoc,
title:'Click to zoom'
});
google.maps.event.addListener(marker,'click',function() {
map.setZoom(map.getZoom()+1);
map.setCenter(marker.getPosition());
});
marker.setMap(map);
}
google.maps.event.addDomListenerOnce(window, 'load', initialize);
When lat long and city are initialized, initialized function is called with lat and long as parameters.
problem
When arguments are passed to initialize function to initialize google map, it shows that function is called as it alerts the values of parameters in called function.lat and long both are string of type as required. but this does not show google map.

Print out coordinates from a geocoding script

I want to print out the coordinates calculated by a geocoding javascript ( maded with Google api V3 ), how can i do that??
and then, how can i pass this values to two variables ($Lat and $Long) that are in a php file that generate a google map maded in Api V2 ??
thanks.
this is my javascript code:
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=HERE MY API KEY" type="text/javascript"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript" src="http://code.google.com/apis/gears/gears_init.js"></script>
<script type="text/javascript">
function getLocale(){
if ( navigator ) {
if ( navigator.userLanguage ) {
return navigator.userLanguage.toLowerCase();
}
else if ( navigator.language ) {
return navigator.language.toLowerCase();
}
else if ( navigator.browserLanguage ) {
return navigator.browserLanguage.toLowerCase();
}
else if ( navigator.systemLanguage ) {
return navigator.systemLanguage.toLowerCase();
}
}
return "unknown";
}
var locales = new Object();
locales["en-gb"] = {lat:54.559322587438636, lng:-4.1748046875, location:"United Kingdom"};
locales["en-us"] = {lat:38.41055825094609, lng:-100.37109375, location:"USA"};
// TODO - more locales
function showMap(latLong, zoom){
var options = {
zoom: zoom,
center: latLong,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), options);
var marker = new google.maps.Marker({
position: latLong,
map: map,
title:"Your location"
});
}
function TryGoogleLoader(){
if (google.loader.ClientLocation != null) {
var address = google.loader.ClientLocation.address;
var yourLocation = address.city + ", " + address.region + ", " + address.country;
document.getElementById("location").innerHTML = "Your location (using Google loader) is " + yourLocation;
var latLong = new google.maps.LatLng(google.loader.ClientLocation.latitude,
google.loader.ClientLocation.longitude);
showMap(latLong, 12);
}
else {
// map locale to location
var locale = getLocale();
if (locales[locale] != null) {
var latLong = new google.maps.LatLng(locales[locale].lat, locales[locale].lng);
document.getElementById("location").innerHTML =
"Guessing your location based on your locale - " + locales[locale].location;
showMap(latLong, 5);
}
else {
document.getElementById("location").innerHTML = "Your location can not be found - locale is " + locale;
}
}
}
function TryGoogleGears(){
if (google.gears) {
// Try Google Gears Geolocation
var geo = google.gears.factory.create('beta.geolocation');
geo.getCurrentPosition(function(position) {
var latLong = new google.maps.LatLng(position.latitude, position.longitude);
document.getElementById("location").innerHTML = "Found location via Google Gears";
showMap(latLong, 15);
}, function() {
TryGoogleLoader();
});
}
else
TryGoogleLoader();
}
window.onload = function() {
// try W3C standard approach
var geoTimeout = 10000;
var timeOuthandler = setTimeout("TryGoogleGears()", geoTimeout);
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
clearTimeout(timeOuthandler);
var latLong = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
document.getElementById("location").innerHTML = "Found location via W3C standard";
showMap(latLong, 15);
}, function() {
// something went wrong, try Google Gears
clearTimeout(timeOuthandler);
TryGoogleGears();
}, {timeout:geoTimeout});
}
else
TryGoogleGears();
}
</script>
how can i print with an alert code the value of the "var latLong"?
how can i pass this value to a set of php variables like $lat and $long?
thanks.
On the W3C function you could do this on success
document.getElementById("location").innerHTML = position.coords.latitude +", "+position.coords.longitude;
On the TryGoogleGears function you could do this on success
document.getElementById("location").innerHTML = position.latitude +", "+position.longitude;
In order to pass the LatLong pair back to PHP you will need to use a XMLHTTPRequest or something similar. This is because PHP is a server side script that executes before JavaScript does, which runs on the client. So to tell PHP something you need to either load a new page and pass the data from JavaScript to PHP with headers, GET, or POST variables. You can either load this page the normal way in the browser and your users see a redirect or you can load it in the background using XMLHTTPRequest.

How can I get lat/lang with Geocode?

I have an address, and now I need to retrieve the Lat / Lang coordinates.
At Google, they only have good examples for V2 and not V3.
I want to do the following:
var myLatLAng = getLatLang(adress);
How can I modify this code to make that happend?
function showAddress(address) {
geocoder.getLatLng(
address,
function(point) {
if (!point) {
alert(address + " not found");
} else {
map.setCenter(point, 13);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(address);
}
}
);
}
You cannot return any value because getLatLng is using callback function so it can only interact with your enviroment.
You can assign it to some other variable
var lat, lng;
function showAddress(address) {
...
} else {
lat = point.lat();
lng = point.lng();
orExecuteOtherfunction();
}
}
Or execute some other function that will do something with your returned point.

Categories