I'm calling a chain of functions through one click function, like below (simplified from my actual code). The problem is, initMap() is running before the user clicks the <button>, throwing an error, because the latitude/longitude are not defined until the user inputs an address through the click() function.
How can I prevent initMap() from running before the click() function?
$("button").click(function() {
var user_search = $("input").val();
var url = "https://api.mapbox.com/geocoding/v5/mapbox.places/" + user_search + ".json?access_token=MYAPIKEY";
$.getJSON(url, function(data) {
var number = data.features[0].address;
var route = data.features[0].text;
var latitude = data.features[0].geometry.coordinates[1];
var longitude = data.features[0].geometry.coordinates[0];
initMap(latitude, longitude);
});
});
var map;
var infowindow;
// Create Google Map with location at center
function initMap(latitude, longitude) {
var location = {lat: latitude, lng: longitude};
console.log(location);
map = new google.maps.Map(document.getElementById('map'), {
center: location,
zoom: 15
});
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: location,
radius: 3200,
types: ['school']
}, callback);
}
// List nearby places
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
listPlaces(results[i]);
}
}
else {
alert("There was an error finding address data.")
}
}
// ONLY list places with characteristics below
function listPlaces(place) {
if (place.name.indexOf('High ') > -1 && place.name.indexOf('Junior') == -1) {
$('body').append('<br>' + place.name);
}
}
ur initMap function is not getting closed properly.the error is because of syntax error not because of initMap() running without button click
$("button").click(function() {
initMap(latitude, longitude);
});
function initMap(latitude, longitude) {
//do stuff
callback();
}
function callback(results, status) {
//do stuff
}
function listPlaces(place) {
//do more stuff
}
Did this is the real code you want?
$("button").click(function() {
initMap(latitude, longitude);
});
function initMap(latitude, longitude) {
//do stuff
}
function callback(results, status) {
//do stuff
}
function listPlaces(place) {
//do more stuff
}
Related
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!
I have an object inside an Angular.js factory:
angular.module('myapp')
.factory('geoLocationService', function () {
var geoLocationObj = {};
var geocoder = new google.maps.Geocoder();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(_successFunction, _errorFunction);
}
function _successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (results[2]) {
geoLocationObj.resultCity = results[2].formatted_address;
alert(geoLocationObj.resultCity);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
return geoLocationObj;
});
This works alert(geoLocationObj.resultCity); and alerts in property value
But
console.log(geoLocationObj);
does not log the propety geoLocationObj.resultCity
I am trying to use geoLocationObj.resultCity outside the Factory in my controller but it is not there.
I have in my controller:
.controller('IndexCtrl', function ($scope, geoLocationService) {
var geoLocationService = geoLocationService;
console.log(geoLocationService);
geoLocationService is an empty Object
I cannot figure out why this is happening.
Can you help me with this?
The problem in your code is that your object is initialize in the callback (_successFunction) that means that the returned object is still empty because the _successFunction hasn't been called.
You should return a promise using $q and call .then() in your controller.
angular.module('myapp')
.factory('geoLocationService', ['$q', function ($q) {
var geoLocationObj = {};
var deferred = $q.defer();
var geocoder = new google.maps.Geocoder();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(_successFunction, _errorFunction);
}
function _successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (results[2]) {
deferred.resolve(results[2].formatted_address);
alert(geoLocationObj.resultCity);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
return deferred.promise;
})];
And in your controller
.controller('IndexCtrl', function ($scope, geoLocationService) {
geoLocationService.then(function(geoLocObj){
console.log(geoLocObj); Here your object has been resolved
});
Your factory should return something like this
angular.module('myapp')
.factory('geoLocationService', function() {
return{
geoLocationObj:function(){
var geocoder = new google.maps.Geocoder();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(_successFunction, _errorFunction);
}
function _successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (results[2]) {
geoLocationObj.resultCity = results[2].formatted_address;
alert(geoLocationObj.resultCity);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
return geoLocationObj
}
}
});
You can call in your controller like this
angular.module('myapp', [])
.controller('IndexCtrl', function ($scope, geoLocationService) {
var promise = geoLocationService.geoLocationObj()
promise.then(function(success){
console.log("me "+success);
},function(error){
console.log("They eat all my candies :" +error)
})
});
You can play it here in Js bin
PS. You need to include your google map libs
I am working with the google maps API and whenever I return the variable to the initialize function from the codeLatLng function it claims undefined. If I print the variable from the codeLatLng it shows up fine.
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
var addr = codeLatLng();
document.write(addr);
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
return results[1].formatted_address;
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
prints out undefined
If I do:
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
codeLatLng();
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
document.write(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
prints out New York, NY 10012, USA
You can't return the value from the function, the value doesn't exist yet when the function returns.
The geocode method makes an asynchonous call and uses a callback to handle the result, so you have to do the same in the codeLatLng function:
var geocoder;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(40.730885,-73.997383);
codeLatLng(function(addr){
alert(addr);
});
}
function codeLatLng(callback) {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
callback(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
You're making an asynchronous request, your codeLatLng() function has finished and returned long before the geocoder is done.
If you need the geocoder data to continue, you'll have to chain your functions together:
function initialize() {
geocoder = new google.maps.Geocoder();
codeLatLng();
}
function codeLatLng() {
var latlng = new google.maps.LatLng(40.730885,-73.997383);
if (geocoder) {
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
initContinued(results[1].formatted_address);
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
}
function initContinued(addr) {
alert(addr);
}
You can get value using localstorage.
geocoder.geocode({
'address': address,
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latitude = results[0].geometry.location.lat();
var longitude = results[0].geometry.location.lng();
}
localStorage.setItem("endlat", latitude);
localStorage.setItem("endlng", longitude);
});
var end_lat = localStorage.getItem("endlat");
var end_lng = localStorage.getItem("endlng");
But it returns previous value.. Returns current value when we click twice...
pass geocoder as a parameter to the codeLatLng() function.
function codeLatLng(geocoder) {
call it like so in your initialize function:
var addr = codeLatLng(geocoder);
That return is not returning from codeLatLng; it's returning from the anonymous function being passed to geocoder.geocode.
I think you'll need to pass the data using another mechanism e.g. a global variable
I'm trying to return the variable coord from GetLocation, but it only returns undefined.
Any help appreciated!
var coord = "";
function GetLocation(address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { "address": address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
coord = ParseLocation(results[0].geometry.location);
// This alert shows the proper coordinates
alert(coord);
}
else{ }
});
// this alert is undefined
alert(coord);
return coord;
}
function ParseLocation(location) {
var lat = location.lat().toString().substr(0, 12);
var lng = location.lng().toString().substr(0, 12);
return lat+","+lng;
}
When you are returning coords from the outer function it is still in fact undefined. The inner function executes later when the asynchronous operation (if it wasn't asynchronous, the API would just give the result to you normally) is done.
Try passing a callback:
function GetLocation(address, cb) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { "address": address }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
cb(ParseLocation(results[0].geometry.location));
}
else{ }
});
}
You can then use it like so:
GetLocation( "asd", function(coord){
alert(coord);
});
I'm trying to use the Google geocoder API V3 to plot a location on a map based on an address specified by the user, code is below.
When I make a request directly (e.g. to http://maps.googleapis.com/maps/api/geocode/json?address=peterborough&sensor=false) I get the expected response. However, when I make the same request using the code below, the midpoint variable is always undefined after the getLatLong function has exited.
What am I doing incorrectly?
function loadFromSearch(address)
{
midpoint = getLatLong(address);
mapCentre = midpoint;
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
...
}
function getLatLong(address)
{
var result;
var url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address) + '&sensor=false'
$.getJSON(url,
function (data){
if (data.status == "OK")
{
result = data.results[0].geometry.location;
}
});
return result;
}
==================================================================================
In light of responses, I have now updated the code to the following. I'm still not getting any result though, with breakpoints set in Firebug the result = data.results[0].geometry.location; never gets hit.
function loadFromSearch(address)
{
midpoint = getLatLong(address, loadWithMidpoint);
}
function getLatLong(address, callback)
{
var result;
var url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address) + '&sensor=false'
$.getJSON(url,{},
function (data) {
if (data.status == "OK")
{
result = data.results[0].geometry.location;
callback(result);
}
});
}
function loadWithMidpoint(centre)
{
mapCentre = centre;
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
...
}
=============================================================================
I have it! The final code, which works, looks like this:
function loadFromSearch(coordinates, address)
{
midpoint = getLatLong(address, latLongCallback);
}
function getLatLong(address, callback)
{
var geocoder = new google.maps.Geocoder();
var result = "";
geocoder.geocode({ 'address': address, 'region': 'uk' }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK)
{
result = results[0].geometry.location;
latLongCallback(result);
}
else
{
result = "Unable to find address: " + status;
}
});
return result;
}
function latLongCallback(result)
{
mapCentre = result;
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
...
}
If you are using V3 of the API cannot you use the this?
function findAddressViaGoogle() {
var address = $("input[name='property_address']").val();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address, 'region': 'uk' }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
newPointClicked(results[0].geometry.location)
} else {
alert("Unable to find address: " + status);
}
});
}
The above is what I use to find some lat long cordinates of an inputted address, May work better?
EDIT:
function loadFromSearch(address)
{
midpoint = getLatLong(address);
mapCentre = midpoint;
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
...
}
function getLatLong(address)
{
var geocoder = new google.maps.Geocoder();
var result = "";
geocoder.geocode( { 'address': address, 'region': 'uk' }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
result = results[0].geometry.location;
} else {
result = "Unable to find address: " + status;
}
});
return result;
}
The problem is your $.getJSON function is asynchronous, yet you are returning the 'result' synchronously.
You need to do something like this (not tested!)
function loadFromSearch(address)
{
midpoint = getLatLong(address, function(midpoint){
// this is a callback
mapCentre = midpoint;
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
...
});
}
function getLatLong(address, callback)
{
var result;
var url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address) + '&sensor=false'
$.getJSON(url,
function (data) {
if (data.status == "OK") {
result = data.results[0].geometry.location;
callback(result) // need a callback to get the asynchronous request to do something useful
}
});
}
In response to your edit: Oh dear, it looks like the V3 geocoder does not support JSONP. This means you can not do a cross-domain request to get data from it in your browser. See http://blog.futtta.be/2010/04/09/no-more-jsonp-for-google-geocoding-webservice/
However Brady's solution does work. I guess that is the way Google want us to geocode now.