What script to include for both Google Places and Geocoding - google-maps

I'm struggling to get a Google Places lookup AND Geocoding to work together in the same page. I think there's a conflict in how I'm loading the two APIs.
I'm using this one to load the places API
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&key=*****************&callback=initAutocomplete&types=address" async defer></script>
Places lookup works fine with that.
For Geocoding, this is the first line of code I'm trying to get working
geocoder = new google.maps.Geocoder();
And it works (well, doesn't throw an error) if I include this in my page:
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
But that's pretty much the same URL I already have, and including it breaks the Places lookup. When I have both scripts included I also get a warning telling me I've included the Maps API multiple times which may cause problems.
Please could someone show me which script(s) to include for both to work together? I'm finding the docs pretty confusing at this point to be honest.

It should work fine with just your first include. It contains the base Google Maps API plus the Places library.
var initMap = function () {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
address: '10 Downing St, Westminster, London SW1A 2AA, UK',
}, function (results, status) {
if (status === 'OK') {
var result = results[0];
alert('latitude: ' + result.geometry.location.lat());
}
else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
};
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&callback=initMap" async defer></script>

Related

SAP Fiori can not create geocoder constructor on the first view call

I would like to implement the GoogleMaps - GeoCoding API which should use the address attributes from a businesspartner to receive the related coordinates (lat,lng).
Please note: i extend an SAP Fiori App which is called by the SAP Fiori Lauchnpad, i don't develop a SAPUI5 from scratch.
But I have an issue.
While i was loading the app, it's not possible to create the constructor of Geocoder API in the code.
Error Message: "Uncaught TypeError: google.maps.Geocoder is not a
constructor"
I just want to execute the simple standard code in the controller:
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { "address": address }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
var location = results[0].geometry.location;
var lat = location.lat();
var lng = location.lng();
alert("Latitude: " + lat);
alert("Longitude: " + lng);
}
});
Obviously i load the third party library (google maps - GEOCODING API) not.
But i don't find any good examples, how to load an external library in an SAP FIORI App.
The approaches of the following link doesn't work:
https://a.kabachnik.info/how-to-include-external-javascript-libraries-in-sap-ui5.html
Method 2 would be fine, but it doesn't work.
My Current Project Structure is:
The peace of code for this approach brings no solution:
var theRootPath = jQuery.sap.getModulePath("cus.crm.myaccounts.zcrm_myacc_ext");
jQuery.sap.registerModulePath('lib.google.library', theRootPath + '/lib/google/library');
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel",
"lib/google/library"
], function(Controller, JSONModel, library) {
//call geocoding api
}
I am talking about a standard Fiori APP extension, so i don't use the index.html. I don't create a SAPUI5 App too... just for SAP FIORI EXTENSIONS.
I hope someone can help me how to integrate a third party library.

Google Places API not returning place_id

I've noticed the message about Google deprecating reference in favour of place_id and was looking to implement it.
I am using the AutocompleteService but when I run it the response does not contain place_id, but does contain reference and id.
Here's a quick adaptation I did of the example page (I tried to put it on jsfiddle but couldn't get it to run):
<!DOCTYPE html>
<html>
<head>
<title>Retrieving Autocomplete Predictions</title>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
<script>
// This example retrieves autocomplete predictions programmatically
// from the autocomplete service, and displays them as an HTML list.
// The predictions will include a mix of places (as defined by the
// Google Places API) and suggested search terms.
function initialize() {
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({ input: 'trafalgar square' }, callback);
}
function callback(predictions, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
var results = document.getElementById('results');
for (var i = 0, prediction; prediction = predictions[i]; i++) {
results.innerHTML += '<li>' + prediction.description + '</li>';
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<p>Query suggestions for 'trafalgar square':</p>
<ul id="results"></ul>
</body>
</html>
Can someone explain what I'm missing / doing wrong?
Has someone got an example of the AutocompleteService with place_id being returned with the predictions/suggestions?
Thanks
Issue 6845
Bug: Google Maps JavaScript API - Autocomplete Response not included place_id
https://code.google.com/p/gmaps-api-issues/issues/detail?id=6845&q=place_id&colspec=ID%20Type%20Status%20Introduced%20Fixed%20Summary%20Stars%20ApiType%20Internal
UPDATE
This issue has been fixed
https://code.google.com/p/gmaps-api-issues/issues/detail?id=6845#makechanges
I can confirm what you're seeing. I'd guess we just need to wait for the roll out to be complete.

Displaying multiple Google Maps asynchronously

I currently have a page which shows results of a search. When the user clicks on a result, details are fetched using ajax and loaded into the page. In these details, there is a Google map.
Previously, I had the Gmaps script with callback in the details page. But I ran into this problem that the Gmaps script was inserted multiples times if the user clicked on several results.
Now, I load the script in the results page and the details page calls the initialize function while passing all the necessary parameters. But I get an undefined is not a function error.
So my question is: how to structure the Gmaps script, callback, and asynchronous initializing of the maps between the two pages (results, and details)?
results page
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key=[key]"></script>
function initialize(params) {
var directionsService, directionsDisplay, map;
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
// your typical gmaps stuff
}
details page
<div id="map_canvas"></div>
initialize(params);
You can just see if the Google Map's script has already loaded by checking for the "google" global variable that gets added to the DOM.
Full jsfiddle example here: http://jsfiddle.net/gavinfoley/yD8Qt/.
// dom ready
$(function () {
if (typeof google === "undefined") {
alert("Lazy loading Google maps");
lazyLoadGoogleMaps();
} else {
alert("Google Maps is already loaded");
googleMapsLoaded();
}
});
function lazyLoadGoogleMaps() {
// Note the callback function name
$.getScript("http://maps.google.com/maps/api/js?sensor=true&callback=googleMapsLoaded")
.done(function (script, textStatus) {
alert("Google maps loaded successfully");
})
.fail(function (jqxhr, settings, ex) {
alert("Could not load Google Maps: ", ex);
});
}
// This function name is passed in to the Google maps script load above
// and will be called once Google maps has loaded
function googleMapsLoaded() {
alert("Done!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

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

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.