Callback with geocoder.geocode - javascript

I have some issue with the callback inside geocoder.geocode.
var tri = new Array();
for (var j = 1; j < taille; j++) {
where = getBoutique[j].adresse + ", " + getBoutique[j].ville;
boutiqueProche(lat, lon, where, function (distanceO) {
//window.localStorage.setItem("distance", distance);
console.log(distanceO);
tri.push(distanceO);
//return distance;
//console.log("Nous somme dans "+localStorage.getItem("distance"));
});
console.log("Inside " + tri);
}
function boutiqueProche(cLat, cLong, where, callback) {
var geocoder = new google.maps.Geocoder();
var currentPosition = new google.maps.LatLng(cLat, cLong); // On récupère nos info
var recup = getBoutique.length;
var distance;
geocoder.geocode({
'address': where
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var laBoutique = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
distance = google.maps.geometry.spherical.computeDistanceBetween(currentPosition, laBoutique);
recup = distance / 1000;
callback(recup);
} else {
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
setTimeout(function () {
boutiqueProche(cLat, cLong, where, callback); // rappel fonction avec meme param
}, 200);
} else { /*Faire quelque chose */ }
}
});
}
I want to fill the array tri with the data from recup variable. But when I fill tri, nothing happens. It is empty.
What is the problem?

Related

Undefined Issue using Google's Javascript API

I've been stuck on an issue for a number of days when using the google geo-location api. This is what I've been trying -
function codeAddress(address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({"address": address}, function(results, status) {
if (status == "OK") {
return results[0].geometry.location;
} else {
return null;
}
});
}
function generateJSON(origin, destination) {
var origin_loc = codeAddress(origin);
var dest_loc = codeAddress(destination);
....
}
The "origin_loc" variable is coming back unassigned and I haven't been able to figure out why with the debugger. When I log the results[0] to the console it is coming back fine with the object.
Does anyone have any ideas why this is happening?
Thanks
This is what worked for me in the end -
function codeAddresses(addresses, callback) {
var coords = [];
for(var i = 0; i < addresses.length; i++) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address':addresses[i]}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
coords.push(results[0].geometry.location);
if(coords.length == addresses.length) {
callback(coords);
}
}
else {
throw('No results found: ' + status);
}
});
}
}
function generateJSON(origin, destination) {
var addresses = [origin, destination];
codeAddresses(addresses, function(coords) {
var json = { ..... }
....
});
}
Thanks for your help #yuriy636!

Map does not load centered when doing first search

Can anyone tell me why the map does not load centered the first time it loads? It works fine when I do a second search, but never loads up correctly the first time.
src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"
var directionsDisplay;
var directionsService;
var geocoder;
var currentAddress = 'placeholder';
var tabCount = 0;
var altRouteCount = 0;
var savedRoutes;
$(document).ready(function(){
$('#message-container').hide (0);
document.getElementById('sidebar').className = 'sidebar-hidden';
// Keeps form pointAB from refreshing the page.
$('#pointAB').on('submit', function (e) {
e.preventDefault();
});
$('#tabs').tab();
$('#tabs a').click( function (e) {
e.preventDefault();
$(this).tab('show');
});
$('#sidebar #togglebtn').click(toggleSidebar);
$('#deletes').click(deleteTabs);
$('#routeChange').click(function () {
var index = $('#routeChange').data('route');
index = (index+1)%altRouteCount;
deleteTabs();
printRoute (savedRoutes, index);
$('#routeChange').data('route', index);
});
// Call Google Direction
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
// Google Autocomplete
var start_input = document.getElementById('start');
var end_input = document.getElementById('end');
var bounds = new google.maps.LatLngBounds(
new google.maps.LatLng(40.532980, -74.118551),
new google.maps.LatLng(40.895218, -73.735403)
);
// Bounds right now only restrict country
var start_autocomplete = new google.maps.places.Autocomplete((start_input),{
// bounds: {sw:new google.maps.LatLng(40.895218, -73.735403), ne:new google.maps.LatLng(40.532980, -74.118551)},
componentRestrictions: {country: 'us'}
}
);
var end_autocomplete = new google.maps.places.Autocomplete((end_input),{
// bounds: {sw:new google.maps.LatLng(40.895218, -73.735403), ne:new google.maps.LatLng(40.532980, -74.118551)},
componentRestrictions: {country: 'us'}
}
);
start_autocomplete.setBounds(bounds);
end_autocomplete.setBounds(bounds);
// Initial map
function initialize() {
var map;
var pos;
// Default pos for map will be center of Manhattan
if(!pos){
pos = new google.maps.LatLng(40.784148400000000000, -73.966140699999980000);
}
var mapOptions = {
zoom: 13
};
getAddress();
// Draw Map
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
map.setCenter(pos);
// Google Direction text route
directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directions-panel'));
//Needed to resize maps
google.maps.event.addDomListener (map, 'idle', function(){
google.maps.event.trigger (map, 'resize');
});
}
// Load Map
google.maps.event.addDomListener(window, 'load', initialize);
});
/************************************************
Site Navigational Elements
************************************************/
function toggleSidebar() {
var state = $('#sidebar').data('toggle');
if (state == 'hidden') {
document.getElementById('sidebar').className = "sidebar-appear";
$('#sidebar').data('toggle', 'shown');
}
else if (state == 'shown') {
document.getElementById('sidebar').className = "sidebar-hidden";
$('#sidebar').data('toggle', 'hidden');
}
};
function nextSlide() {
$('#navCarousel').carousel('next');
};
function prevSlide(){
$('#navCarousel').carousel('prev');
};
/************************************************
UI Messages
************************************************/
function hideMessage(){
$('#init-message').hide(1000);
};
function pushMessage (messageType, message) {
$('#message-container').hide (0);
if (messageType == 'error') {
document.getElementById('message-container').className = "alert alert-danger";
document.getElementById('icon').className = "glyphicon glyphicon-remove-sign";
}
else if (messageType == 'success') {
document.getElementById('message-container').className = "alert alert-success";
document.getElementById('icon').className = "glyphicon glyphicon-ok-sign";
}
else if (messageType == 'warn') {
document.getElementById('message-container').className = "alert alert-warning";
document.getElementById('icon').className = "glyphicon glyphicon-exclaimation-sign";
}
else {
//Congrats. Senpai has noticed your ability to break shit. Rejoice.
console.error ("Please check your messageType.")
}
$('#message').text(message);
$('#message-container').show (1000);
};
/************************************************
Information Retrieval
************************************************/
// Get current location button function
function getAddress(callback){
geocoder = new google.maps.Geocoder();
// If geolocation available, get position
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successCallback, errorCallback, {timeout:60000,maximumAge:60000});
}
//Else, browser doesn't support geolocaiton
else {
pushMessage ('error', 'Your browser doesn\'t support geolocation.');
console.log("Browser doesn't support geolocaiton");
}
// Optional callback
if (callback){
callback();
}
};
function successCallback(position){
var pos = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
//Reverse geocoding for current location
geocoder.geocode({'latLng': pos}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results.length != 0) {
currentAddress = results[0].formatted_address;
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
};
function errorCallback(){
};
fillAddress = function() {
if (currentAddress != 'placeholder') {
$('#start').val (currentAddress);
pushMessage ('success', "Got your current location!");
}
else {
pushMessage ('warn', 'Please share your location to use this feature.');
}
};
// Set route and request direction result
function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
if (start == '' && end == '') {
pushMessage ('error', "Please fill in your current location and destination.");
start='';
end='';
return;
}
else if (start == '') {
pushMessage ('error', "Please fill in your current location.");
start='';
end='';
return;
}
else if (end == '') {
pushMessage ('error', "Please fill in your destination.");
start='';
end='';
return;
}
else {
start += ' new york city';
end += ' new york city';
}
var request = {
origin: start,
destination: end,
provideRouteAlternatives: true,
travelMode: google.maps.TravelMode.TRANSIT
};
deleteTabs();
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
altRouteCount = response.routes.length;
savedRoutes = response;
printRoute (savedRoutes, 0);
//Move to next slide when directions have been retrieved.
$('#navCarousel').carousel('next');
//Disable loading icon pseudocode.
//$('#loadingIcon').hide(300);
savedRoutes = response;
}
else {
//If DirectionsStatus.NOT_FOUND
//or DirectionsStatus.ZERO_RESULTS
pushMessage ('error', 'No directions found.');
}
});
};
function printRoute (routeObj, routeNo) {
// Get route object
var thisRoute = routeObj.routes[routeNo].legs[0];
for (var i = 0; i < thisRoute.steps.length; i++) {
// Find all possible transit
if (typeof thisRoute.steps[i].transit != 'undefined'
&& thisRoute.steps[i].transit.line.vehicle.type == "SUBWAY") {
trainTab (thisRoute.steps[i]);
}
}
}
//Get details from Maps API json object
function getTransitDetail(obj, tabNo){
var parent='';
if (tabNo) {
parent='div#tab'+tabNo+' ';
}
$(parent+'#train').text(obj.transit.line.short_name + " Train");
$(parent+'#train-stop-depart').text(obj.transit.departure_stop.name);
$(parent+'#train-stop-end').text(obj.transit.arrival_stop.name);
$(parent+'#num-stop').text(obj.transit.num_stops + " Stops");
$(parent+'#arrival_time').text(obj.transit.arrival_time.text);
$(parent+'#departure_time').text(obj.transit.departure_time.text);
$(parent+'#distance').text(obj.distance.text);
$(parent+'#duration').text(obj.duration.text);
};
// Get current time from device
function getTime(){
var currentdate = new Date();
var datetime = currentdate.getDate() + "/"
+ (currentdate.getMonth()+1) + "/"
+ currentdate.getFullYear() + " # "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();
return datetime;
};
function makeNewTab() {
var prevTab = 'tab' + tabCount;
tabCount++;
var newTab = 'tab' + tabCount;
console.log ('New Tab.');
//Adds tab to nav bar
$('#routeChange').before('<li>TAG LABEL</li>');
//Adds contents of tab
$('div.tab-content #'+prevTab).after('<div id="'+newTab+'"></div>');
$('#'+newTab).addClass("tab-pane");
};
function deleteTabs() {
var thisTab;
while (tabCount >= 1) {
thisTab = 'tab' + tabCount;
//Remove tab from nav bar
$('ul#tabs li a[href="#'+thisTab+'"]').remove();
//Remove contents of tab
$('#'+thisTab).remove();
tabCount--;
}
tabCount = 1;
$('#tabs a:first').tab('show');
};
function trainTab (obj) {
makeNewTab();
$('ul#tabs li a[href="#tab'+tabCount+'"]').text(obj.transit.line.short_name);
$('#tab'+tabCount).append (
'<div id="station-info" class="col-xs-11 col-xs-height col-sm-12 col-sm-height">\
<p>Station Info:</p>\
<p id="train"></p>\
<p id="train-stop-depart"></p>\
<p id="train-stop-end"></p>\
<p id="num-stop"></p>\
<p id="arrival_time"></p>\
<p id="departure_time"></p>\
<p id="distance"></p>\
<p id="duration"></p>\
<!-- <%= link_to "an article", #station%> -->\
</div>');
getTransitDetail (obj, tabCount);
};
Is it because of the order of my code? I tried playing around with the order and could not find a solution. Any help would be appreciated. Thanks in advance!

jQuery .each loop - Call Function inside

How do I call function inside jQuery .each?
At the moment my function is performed only the last time.
How can I edit this to execute every time the function MyCurrentPosition(dsRow) is called?
This is the code:
Maps.GetCoordinates = function (jsonResponse) {
jQuery.each(jsonResponse, function(filterName,result) {
var risultati = result;
var items = risultati.rows;
//console.log (risultati.total);
if(risultati.total > 0)
{
jQuery.each(items, function(i,dsRow) {
var myhtml= dsRow.latitude;
//This work all time
jQuery('#show_distance_'+dsRow.id).html(myhtml).show();
//but this function only last time print result
MyCurrentPosition(dsRow);
});
}
}); //end foreach
}
EDIT: This is the MyCurrentPosition function :
var options = { enableHighAccuracy: true, timeout: 12000, maximumAge: 0 };
function MyCurrentPosition(dsRow) {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (pos) {
crd = pos.coords;
HelloMapsSearch.GetDistance(crd,dsRow);
},
showError,
options );
} else {
alert("Geolocation is not supported by your device.");
}
//return crd;
}
HelloMapsSearch.GetDistance = function (crd,dsRow) {
var origine = crd;
var destinazione = dsRow;
var mxstart = new google.maps.LatLng(origine.latitude,origine.longitude);
var mxend = new google.maps.LatLng(destinazione.latitude, destinazione.longitude);
var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [mxstart],
destinations: [mxend],
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
//}, callback );
}, function(response, status) {callback(response, status, dsRow)});
}
function callback(response, status, dsRow) {
if (status != google.maps.DistanceMatrixStatus.OK) {
alert('Error was: ' + status);
} else {
var origins = response.originAddresses;
var destinations = response.destinationAddresses;
var outputDiv = document.getElementById('show_distance_'+dsRow.id);
outputDiv.innerHTML = '';
for (var i = 0; i < origins.length; i++) {
var results = response.rows[i].elements;
for (var j = 0; j < results.length; j++) {
outputDiv.innerHTML += "Origine:"+origins[i] + '<br> to destinazione:' + destinations[j] + '<br>'
+ ': ' + results[j].distance.text + ' in '
+ results[j].duration.text + '<br>';
}
}
}
}
A few things to check out. jsonResponse must be an array. risultati must also have rows that is of type Array.
As for the function inside called MyCurrentPosition, we are currently missing on the implementation itself.
Does it have an if inside that prevents logging? Share the code please.

Javascript/jQuery - waiting until function complete before running the rest

Hi I have a button which when it gets clicked triggers a function. The function does some stuff (reverse geocodes a latitude/longitude) and then fills a hidden form input with a value.
I need the input to have the correct value before the rest of the code I need gets executed, is there a way to do this? At the moment I have
$('.addButton').click(function() {
//first run the reverse geocode to update the hidden location input with the readable address
reversegeocode();
var location = $("#location").val();//the value I need
$.post("<?php echo $this->webroot;?>locations/add", {location:location})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
So basically I don't want to get the value from the input and post it via AJAX until I know that the reversegeocode() function has finished
Can anyone please explain how I can go about this. I've read some stuff about deferment but I'm absolutely useless at figuring out Javascript and I'm really struggling.
Thanks
EDIT:
Here's my reversegeocode funciton
function reversegeocode(){
var lat = $('#lattitude').val();
var lng = $('#longitude').val();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {//http://stackoverflow.com/questions/8082405/parsing-address-components-in-google-maps-upon-autocomplete-select
var address_components = results[0].address_components;
var components={};
jQuery.each(address_components, function(k,v1) {jQuery.each(v1.types, function(k2, v2){components[v2]=v1.long_name});})
var output = '';
var needAcomma = false;
if(components.route != undefined) {
output += components.route;
needAcomma = true;
}
if(components.locality != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.locality;
needAcomma = true;
}
if(components.administrative_area_level_1 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_1;
needAcomma = true;
}else if(components.administrative_area_level_2 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_2;
needAcomma = true;
}else if(components.administrative_area_level_3 != undefined) {
if(needAcomma) {
output += ', ';
}
output += components.administrative_area_level_3;
needAcomma = true;
}
$("#location").val(output);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
}
Since reversegeocode is a asynchronous method, you need to use a callback based solution. reversegeocode should receive a callback method as a argument and then invoke the callback once the geocoding is completed.
$('.addButton').click(function () {
//pass a callback to reversegeocode which will get called once the geocoding is completed
reversegeocode(function (location) {
//the callback receives the location as a parameter
$.post("<?php echo $this->webroot;?>locations/add", {
location: location
})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
});
function reversegeocode(callback) {
var lat = $('#lattitude').val();
var lng = $('#longitude').val();
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({
'latLng': latlng
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) { //http://stackoverflow.com/questions/8082405/parsing-address-components-in-google-maps-upon-autocomplete-select
var address_components = results[0].address_components;
var components = {};
jQuery.each(address_components, function (k, v1) {
jQuery.each(v1.types, function (k2, v2) {
components[v2] = v1.long_name
});
})
var output = '';
var needAcomma = false;
if (components.route != undefined) {
output += components.route;
needAcomma = true;
}
if (components.locality != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.locality;
needAcomma = true;
}
if (components.administrative_area_level_1 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_1;
needAcomma = true;
} else if (components.administrative_area_level_2 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_2;
needAcomma = true;
} else if (components.administrative_area_level_3 != undefined) {
if (needAcomma) {
output += ', ';
}
output += components.administrative_area_level_3;
needAcomma = true;
}
$("#location").val(output);
//call the callback
callback(output);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
}
Change reversegeocode to take a callback parameter (also known as a continuation).
Encapsulate all the stuff that needs to wait for reversegeocode to finish, putting it into an in-place, nameless function.
(Note the similarity to what you're already doing for the click handler.)
With this approach you are also free to add parameters to the callback, which you can use to pass data directly through.
$('.addButton').click(function() {
reversegeocode(function(some_data) {
var location = $("#location").val();//the value I need
//...stuff...
});
});
function reversegeocode(callback){
//...stuff...
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//...stuff...
} else {
alert('Geocoder failed due to: ' + status);
}
callback(some_data);
});
}
You need to use a callback function in the reversegeocode function.
The same exact way as you do ajax :)
$('.addButton').click(function() {
reversegeocode().done(function(location) {
$.post("<?php echo $this->webroot;?>locations/add", {location:location})
.done(function (data) {
$("#locationsHolder").html(data);
});
});
})
To do this you will have reversegeocode return a jquery deferred promise
function reversegeocode() {
return $.Deferred(function(d) {
//do stuff and when it succeeds
d.resolve(location);
//or if it fails
d.reject("something went wrong");
}).promise();
}

Google maps API returning null zip code (used to work)

I've been using the following code for a while now and noticed it has stopped working and throwing an error. The alert says null. Has the maps API changed? I've loaded up
https://maps.googleapis.com/maps/api/js?sensor=false
and
https://maps.gstatic.com/intl/en_us/mapfiles/api-3/15/5/main.js
function geo(){
if(navigator.geolocation) {
var fallback = setTimeout(function() { fail('10 seconds expired'); }, 10000);
navigator.geolocation.getCurrentPosition(
function (pos) {
clearTimeout(fallback);
console.log('pos', pos);
var point = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);
new google.maps.Geocoder().geocode({'latLng': point}, function (res, status) {
if(status == google.maps.GeocoderStatus.OK && typeof res[0] !== 'undefined') {
var zip = res[0].formatted_address.match(/,\s\w{2}\s(\d{5})/);
alert(zip);
var homecity;
var homezip;
if((zip[1]>21201)&&(zip[1]<21298)) {
//document.getElementById('geo').innerHTML = "Baltimore "+zip[1];
homecity = "Baltimore";
homezip = zip[1];
//$("._res").html(homecity+" "+homezip);
window.location.href = "?city="+homecity+"&zip="+homezip;
}
if((zip[1]>20001)&&(zip[1]<20886)) {
//document.getElementById('geo').innerHTML = "Baltimore "+zip[1];
homecity = "D.C.";
homezip = zip[1];
//$("._res").html(homecity+" "+homezip);
window.location.href = "?city="+homecity+"&zip="+homezip;
}
if((zip[1]>19019)&&(zip[1]<19255)) {
//document.getElementById('geo').innerHTML = "Baltimore "+zip[1];
homecity = "Philadephia";
homezip = zip[1];
//$("._res").html(homecity+" "+homezip);
window.location.href = "?city="+homecity+"&zip="+homezip;
}
}
});
}, function(err) {
fail(err.message+" WTF");
}
);
}
Simple fix, just change the 0 in the res to 1:
var zip = res[1].formatted_address.match(/,\s\w{2}\s(\d{5})/);

Categories