Google Maps geocode: undefined latitude - google-maps

Hitting a page with the follow script displays:
lat: undefined
lon: 51.5001524
Why is it that while lat is undefined, lon is not?
A working example can be found here.
Pull up your web console and see for yourself!
$(document).ready(function(){
var geocoder;
function codeAddress()
{
geocoder = new google.maps.Geocoder();
var address = 'London, England';
geocoder.geocode({'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
lat = results[0].geometry.location.Ia;
lon = results[0].geometry.location.Ja;
console.log("lat: " + lat);
console.log("lon: " + lon);
}
});
}
codeAddress();
});
</script>
</head>
<body>
</body>
</html>
While we're at it - what is the historical significance of Ia and Ja? I presume it relates to the Cartesian unit vectors i and j (predominately used in Engineering) though I'm not sure.
I found other examples online who use .lat for .Ia and .lng for .Ja
These, however, are returning in the console:
function () {
return this[a];
}
Just need a kick in the right direction.
Thank you.

I would use lat() and lng():
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();

This is a designed behaviour of the geocoder: google shifts the identifiers in
geometry.location.Ia;
geometry.location.Ja;
on a weekly basis, i.e. from above to
geometry.location.Ja;
geometry.location.Ka;
and so on, so it is not possible to refer by id to the geocoder result object.

Chances are Google are using a javascript minifier (e.g. http://jscompress.com/) which renames all variables - hence they're subject to change on every build.

Related

Address validation using Google Maps - Check Address

I'm letting users add an address to their posts using Google Maps.
If a user enters nothing for the map or enters odd special characters (#$!##) it crashes the website and gives me this error:
var lat = data.results[0].geometry.location.lat;
^
TypeError: Cannot read property 'results' of undefined
I'm trying to figure out a way to check for this error when the form is submitted. So far I have had zero luck. Is it possible to check for this error?
I've seen code like this but everything in undefined and I'm not sure how to define it in this case and frankly I'm not sure how the code below is operating.
if (status == google.maps.GeocoderStatus.OK) {
var lat = results[0].geometry.location.lat();
var lon = results[0].geometry.location.lng();
searchStores(lat, lon);
} else {
$addressErrorP.removeClass('hide');
}
Thanks for any help!
Figured it out: Simple and works perfectly.
Step 1: Make sure this is on your page.
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
Then
$('#checkingAddress').click(checkGeocode)
function checkGeocode() {
var addr = document.getElementById('location')
// Get geocoder instance
var geocoder = new google.maps.Geocoder()
// Geocode the address
geocoder.geocode({ address: addr.value }, function (results, status) {
if (status === google.maps.GeocoderStatus.OK && results.length > 0) {
alert('looks good')
// set it to the correct, formatted address if it's valid
addr.value = results[0].formatted_address
// show an error if it's not
} else alert('Invalid address')
})
}

Autocomplete on google map API should return only cities

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAiv004_zrkpEL-v1u-LU6QYIkgv7yjT_M&language={{ Lang::getLocale() }}&libraries=places&" />
<script type="text/javascript">
google.maps.event.addDomListener(window, 'load', function () {
var options = {
types: ['(cities)']
};
var places = new google.maps.places.Autocomplete(document.getElementById('location'));
var inputLat = $("input[name*='lat']");
var inputLng = $("input[name*='lng']");
var inputPlaceId = $("input[name*='place_id']");
google.maps.event.addListener(places, 'place_changed', function () {
var place = places.getPlace();
var address = place.formatted_address;
var latitude = place.geometry.location.lat();
var longitude = place.geometry.location.lng();
var placeId = place.place_id;
inputLat.val(latitude);
inputLng.val(longitude);
inputPlaceId.val(placeId);
});
});
$('#location').keypress(function(e) {
if (e.which == 13) {
google.maps.event.trigger(autocomplete, 'place_changed');
return false;
}
});
</script>
I need it to display only cities, but somehow I get countries too.. I don't want to display continents and countries. please help
If you check the autocomplete documentation, it is stated here that:
the (cities) type collection instructs the Places service to return
results that match either locality or administrative_area3
So like you have done, you need the cities as types parameter.
What you can do is to specify the country in the Google API call with a help of region parameter. Just check this tutorial on how to do that.
Here is the sample request:
= javascript_include_tag "http://maps.google.com/maps/api/js?v=3.13&sensor=false&libraries=places&region=UK"
For more information, check this related SO question it may give you an idea on how to solve this issue.
Google maps Autocomplete: output only address without country and city
Is there a way to get only the city name from Google Places API instead of getting the whole location?

google places autocomplete restrict to particular area

My requirement is to get google places autocomplete suggestion only for Bangalore places, but I am not getting places only for Bangalore or within mention latitude longitude.
I want to retireve only below image places in autocomplete textfield.
can someone plz suggest how to achieve the same and where I am going wrong.
Javascript:
<script type="text/javascript">
function initialize1() {
var southWest = new google.maps.LatLng( 12.97232, 77.59480 );
var northEast = new google.maps.LatLng( 12.89201, 77.58905 );
var bangaloreBounds = new google.maps.LatLngBounds( southWest, northEast );
var options = {
bounds: bangaloreBounds,
types: ['(cities)'],
componentRestrictions: {country: 'in'}
};
var input = document.getElementById('searchTextFieldTo');
var autocomplete = new google.maps.places.Autocomplete(input, options);
}
google.maps.event.addDomListener(window, 'load', initialize1);
</script>
TextField:
<input type="text" id="searchTextFieldTo" class="ui-timepicker-hour" style="width:350px;text-align:left;font-style:italic;" placeholder="Enter To location" autocomplete="on" />
Google Provides two ways to achieve this. If you are not satisfied because in countries like India it do not work well, because states and provisions here do not have rectangular or structure boundaries.
1.LatLngBounds (LatLng southwest, LatLng northeast): Where you can give latitude and longitude to form an rectangle.
2. Location (Lat,Lng) & Radius: Where you can give latitude and longitude to form a circle.
But the problem with these approaches they do not provide expected results if you are from countries like India, where states and provisions are not in structured shapes (Rectangular) as in USA.
If you are facing same issue than there is an hack.
With jQuery/Jacascript, you can attach functions which will consistently maintain city name in text input which is bounded with Autocomplete object of Places API.
Here it is:
<script>
$(document).ready(function(){
$("#locality").val(your-city-name) //your-city-name will have city name and some space to seperate it from actual user-input for example: “Bengaluru | ”
});
$("#locality").keydown(function(event) { //locality is text-input box whixh i supplied while creating Autocomplete object
var localeKeyword = “your-city-name”
var localeKeywordLen = localeKeyword.length;
var keyword = $("#locality").val();
var keywordLen = keyword.length;
if(keywordLen == localeKeywordLen) {
var e = event || window.event;
var key = e.keyCode || e.which;
if(key == Number(46) || key == Number(8) || key == Number(37)){
e.preventDefault();
}//Here I am restricting user to delete city name (Restricting use of delete/backspace/left arrow) if length == city-name provided
if(keyword != localeKeyword) {
$("#locality").val(localeKeyword);
}//If input-text does not contain city-name put it there
}
if(!(keyword.includes(localeKeyword))) {
$("#locality").val(localeKeyword);
}//If keyworf not includes city name put it there
});
</script>
(Image:) Before This Hack
(Image:) After This hack
As mentioned in my answer here:
It is currently not possible to restrict results to a specific locality. You can use bounds as you have done so above to bias results towards, but not restricted to places contained within the specified bounds.
If you believe restriction by locality would be a useful feature please file a Places API - Feature Request.
EDIT:
As per 2018-07 it's possible to define the types of places to be retrieved, like cities (which are locality or administrative_area3 according to the API). Check out full answer here.
I think you can try this.
var bangaloreBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(12.864162, 77.438610),
new google.maps.LatLng(13.139807, 77.711895));
var autocomplete = new google.maps.places.Autocomplete(this, {
bounds: bangaloreBounds,
strictBounds: true,
});
autocomplete.addListener('place_changed', function () {
});
Note form xomena:
strictBounds option was added in version 3.27 of Maps JavaScript API which is currently (January 2017) the experimental version.
function initialize() {
var bangaloreBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(12.864162, 77.438610),
new google.maps.LatLng(13.139807, 77.711895));
var options = {
bounds: bangaloreBounds,
componentRestrictions: {country: 'in'},
strictBounds: true,
};
var input = document.getElementById('autocomplete');
var autocomplete = new google.maps.places.Autocomplete(input, options);
}
google.maps.event.addDomListener(window, 'load', initialize);
As in the current documentation for Google javascript Places API here, you can define an array of types of places to be retrieved. In the example below, I set it to retrieve only cities (which are, according to the API, locality or administrative_area3). You can set it retrieve regions, addresses, establishments and geocodes as well.
function initMap() {
var input = document.getElementById('my-input');
var options = {
types: ['(cities)']
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
// the rest of the code ...
}

How to extract latitude and longitude from Google Maps autocomplete

I'm building an web app that uses this code to search for addresses:
http://code.google.com/intl/en/apis/maps/documentation/javascript/examples/places-autocomplete.html
Type there, New York, NY.
So, when the map is loaded in the DOM after the user using the autocomplete option, the user can save the Location Address in the database, and it will be available as it is "ex. New York, NY". But, for the application I need to save also the Latitude and Longitude.
But I have no ideia how to grab them from the Google API.
As a test app, I'm still using the google code.
I guess I should create some HIDDEN fields and assign the latitude and longitude to them as the user chooses the Address.
Any implementation for my problem is welcome!!
Thanks in advance
P.S:
As I'm new in StackOverflow I could't answer myself.
So I'm editing the post, as suggested by stackoverflow, and here is the solution based in Daniel's answer and some researches in the Google Api:
function getLatLng( address )
{
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address' : address }, function( results, status ) {
if ( status == google.maps.GeocoderStatus.OK ) {
var mapLatLng = document.getElementById( 'mapLatLng' ); // mapLatLng is my hidden field, use your own
mapLatLng.value = results[0].geometry.location.lat() + ', ' + results[0].geometry.location.lng();
} else {
alert( "Geocode was not successful for the following reason: " + status );
}
});
}
Daniel is right for the most part, where he is incorrect is his access of the property here:
$('#latitude').val(results[0].geometry.location.Pa)
$('#longitude').val(results[0].geometry.location.Qa)
You should instead use the lat() and lng() functions provided:
$('#latitude').val(results[0].geometry.location.lat())
$('#longitude').val(results[0].geometry.location.lng())
You can use the Google API to get the Longitude and Latitude from your address.
As you already said, you should implement a hidden field where the result should be inserted.
Then you can save the location together with the coordinates.
I recently implemented this function in one of my projects:
function getLatLngFromAddress(city, country){
var address = city +", "+ country;
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
$('#latitude').val(results[0].geometry.location.lat());
$('#longitude').val(results[0].geometry.location.lng());
} else {
console.log("Geocode was not successful for the following reason: " + status);
}
});
}

Latitude and longitude can find zip code?

I am using Google geocoder for lat and lon and my question is, is there a way you can find out zipcode with latitude and longitude?
It's good to note that Google Maps has a new version since this solultion was presented.
Reference: https://developers.google.com/maps/documentation/geocoding/?csw=1#ReverseGeocoding
Here's an updated example for Google Maps v3. It makes use of the Address Components that JIssak mentions above. I should note that there is no fallback. If it fails to find a zip code, it does nothing. This may or may not be important to your script.
var latlng = new google.maps.LatLng(p.coords.latitude, p.coords.longitude);
geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
for (j = 0; j < results[0].address_components.length; j++) {
if (results[0].address_components[j].types[0] == 'postal_code')
alert("Zip Code: " + results[0].address_components[j].short_name);
}
}
} else {
alert("Geocoder failed due to: " + status);
}
});
I think what you are looking for is the address_components[] in the results array. Maybe something like this would work, just typing the below so it might have errors in it but I think you will get the idea.
http://code.google.com/apis/maps/documentation/geocoding/#Results
function (request, response) {
geocoder.geocode({ 'address': request.term, 'latLng': centLatLng, 'region': 'US' }, function (results, status) {
response($.map(results, function (item) {
return {
item.address_components.postal_code;//This is what you want to look at
}
}
[Removed non-working solution for google - see #hblackorby's solution.]
Here's a version that uses openstreetmap.org, much simpler than google's api - coffeescript, then javascript:
getZip = (cb) ->
# try to populate zip from geolocation/google geocode api
if document.location.protocol == 'http:' && navigator.geolocation?
navigator.geolocation.getCurrentPosition (pos) ->
coords = pos.coords
url = "http://nominatim.openstreetmap.org/reverse?format=json&lat=#{ coords.latitude }&lon=#{ coords.longitude }&addressdetails=1"
$.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback',
cache: true,
}).success (data) ->
cb(data.address.postcode)
Here's the compiled javascript:
getZip = function(cb) {
if (document.location.protocol === 'http:' && (navigator.geolocation != null)) {
return navigator.geolocation.getCurrentPosition(function(pos) {
var coords, url;
coords = pos.coords;
url = "http://nominatim.openstreetmap.org/reverse?format=json&lat=" + coords.latitude + "&lon=" + coords.longitude + "&addressdetails=1";
return $.ajax({
url: url,
dataType: 'jsonp',
jsonp: 'json_callback',
cache: true
}).success(function(data) {
return cb(data.address.postcode);
});
});
}
};
Use it like this:
getZip(function(zipcode){ console.log("zip code found:" + zipcode); });
Yahoo's PlaceFinder API provides a good wat to lookup location data by lat/lng:
http://developer.yahoo.com/geo/placefinder/
Here's an example url that they use:
http://where.yahooapis.com/geocode?q=38.898717,+-77.035974&gflags=R
It would seem so:
Source: Google Maps API Service
Geocoding is the process of converting addresses (like "1600
Amphitheatre Parkway, Mountain View, CA") into geographic coordinates
(like latitude 37.423021 and longitude -122.083739), which you can use
to place markers or position the map. The Google Geocoding API
provides a direct way to access a geocoder via an HTTP request.
Additionally, the service allows you to perform the converse operation
(turning coordinates into addresses); this process is known as
"reverse geocoding."
You should also check out this documentation which has some sample code:
Reverse Geocoding
I made a generic function to look for the type that you want. Not always the address_component has zipcode, country, etc and if they do not always are in the same index. Sometimes your array is lenght 8, 6 or whatever. I did it in Typescript, just change a few things to make it vanilla JS.
getPlaceTypeValue(addressComponents: Places[], type: string): string {
let value = null;
for (const [i] of addressComponents.entries()) {
if (addressComponents[i].types.includes(type)) {
value = addressComponents[i].long_name;
break;
}
}
return value;
}
OR
getPlaceTypeValue(addressComponents: any[], type: string): string {
return (addressComponents.find(({ types }) => types.includes(type)) || {}).long_name || null;
}
Example of usage:
this.placesService.getPlaceTypeValue(address.address_components, 'postal_code');
this.placesService.getPlaceTypeValue(address.address_components, 'country');