Address validation using Google Maps - Check Address - google-maps

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')
})
}

Related

Geocoding Service returns uncaught type error: #<Object> object has no method 'apply'

I'm trying to get lat long coordinates from an address using the Google maps api v3 in Wakanda Studio. I have submitted to the Wakanda forum as well. I searched the v3 documentation as well, which basically advises to pass a JSON object and a call back function to geocode, which is displayed in the code below.
The geocode call is also encapsulated in the codeAddress function. When I run the code, I can see the Geocoder JSON object results that include the lat long coordinates. However, I am getting a strange error message:
Uncaught Error Type: Object #<Object> has no method 'apply'
Any pointers would be appreciated, and let me know if you need to see screenshots/details of anything else emailed, since I cannot post screenshots on stack overflow yet.
button1.click = function button1_click (event)
{
$$('map').setCenter("London, England");
var address1 = "911 South Park Street, Kalamazoo, MI, 49001";
geocoder = new google.maps.Geocoder();
if(!geocoder) {
alert("no geocoder available");
} else {
alert("geocoder available");
}
codeAddress(address1);
};
function codeAddress(address) {
var address1 = address;
geocoder.geocode(
{'address': address1},
{onSuccess: function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//setCenter to mid
//addMarker
var lat = results[0].geometry.location.lat;
var lon = results[0].geometry.location.lon;
alert(lat);
} else {
alert("geocoder issue " + status);
}
}
});
}
I also tried something similar in Wakanda, but it seems the browser is blocking the call due to CORS (cross-reference of domains), so I used the below approach.
Wakanda client --> Wakanda Server --> Google Maps API --> Back to Wakanda Server --> Back to Wakanda client
Client side code:
button1.click = function button1_click (event) {
var address = $$("addressField").getValue();
address = encodeURI(address);
// Make call to server
response = $sources.businesses.getGeoCoordinates(address);
address_info = JSON.parse(response);
if (address_info && address_info.status === "OK") {
$$("business_latitude_field").setValue(
address_info.results[0].geometry.location.lat
);
$$("business_longitude_field").setValue(
address_info.results[0].geometry.location.lng
);
alert('We got latitude & longitude of your address.');
} else {
alert("Could not find latitude and longitude of your given address.");
}
}
Server side code - Code of getGeoCoordinates public method in business data class
function (address) {
// Call google geocode service to convert given address into lat / long
if (address) {
var api_url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" + address;
xhr = new XMLHttpRequest();
xhr.open("GET", api_url);
xhr.send();
var response = xhr.responseText;
return response;
}
}
Hope it helps.

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');

Google Maps geocode: undefined latitude

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.

Google Maps API Geocode Synchronously

I was wondering if its possible to geocode something using googlemaps api synchronously so instead of waiting for a callback function to be called, it would wait for a value to be returned. Has anyone found a way to do something like this.
P.S.: I'm using version 3 of the api
Yes, what you are trying to achieve is possible, although a synchronous request is not needed.
Look at this code
function StoreGeo()
{
var address = $('input[name=zipcode]').val() + ', ' + $('input[name=city]').val();
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var ll = results[0].geometry.location.toString();
llarr = ll.replace(/[\(\) ]/g, '').split(',');
for(i = 0; i < llarr.length;i++)
{
$('#form').append($('<input type="hidden" name="'+(i == 0 ? 'lat' : 'long')+'">').val(llarr[i]));
}
$('#form').submit();
}
else
{
alert(status);
}
});
$('#form').unbind('submit');
return false;
}
$(document).ready(function () {
//init maps
geocoder = new google.maps.Geocoder();
$('#form').bind('submit',function() {
StoreGeo();
});
});
So, attach submit handler to the form, when it is submitted do the geo request based on the address info from your form. But at the same time postpone submitting by returning false in the handler.
The response handler will make 2 hidden textfields 'lat' and 'long' and store the response. finally the form is submitted by client script, including the two new fields. At the server side you can store them in the DB.
!! Note that this is possible, but is probably against the google terms, like noted above.
The Geocoder calls your callback function with the value. That's the only way to do it. If it were synchronous, your script would freeze while it waited for the Geocode to process. There really isn't any reason to do it like that.
What exactly are you trying to accomplish?
I simply use a flag during form submit to know when submit should pass or when it should wait for geocoding. When geocoding is done it will then re-submit the form again.
var hasGeocoded = false;
searchFrom.on('submit', function(){
//If not geocoded yet
if (!hasGeocoded) {
var geocoder = new google.maps.Geocoder();
var location = locationEl.val();
geocoder.geocode({'address': location}, function (results, status) {
hasGeocoded = true;
if (status == google.maps.GeocoderStatus.OK) {
$('#coords').val(
results[0].geometry.location.lat() + ',' + results[0].geometry.location.lng()
);
}
searchFrom.submit();
});
return false; //wait for geocoder to finish and re-submit the form
}
return true;
});