I am trying to add a text field for address input using google autocomplete on a page in my JSF application and not having much luck.
I have looked at the following examples in StackOverflow: Google maps Places API V3 autocomplete - select first option on enter and Adding autocomplete to google geocoder and the example at Places autocomplete example to get an idea of what I need to do.
However, all of these examples indicate that I need to include the Google places library by inserting the following:
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
But when I attempt to add this with my other referencee, I get the following error:
Error Traced[line: 18] The reference to entity "libraries" must end with the ';' delimiter.
So I am dead from the start. I have another googleapi reference that gives no errors:
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
so I am at a loss to understand why I get this error.
I have several other questions about the implementation in thexe examples, but right now, I can't get past adding the reference to the google places library.
First, does anyone know how to add the google api reference without getting the error noted above?
Second, does anyone know where I can find an example that actually adds the address autocomplete functionality to a JSF application using a or preferably a PrimeFaces component?
Thanks.
Your tag should look something like:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&sensor=true&key=#{googleAPIKey}"></script>
Note the key parameter - it's optional but recommended, get your API key from Google API Console.
See https://github.com/rootkit007/google-places-facelet for Google Places Autocomplete JSF component
For Google Maps autocomplete example you could use mine.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Places Autocomplete</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"></meta>
<meta charset="utf-8"></meta>
<link href="/maps/documentation/javascript/examples/default.css" rel="stylesheet"></link>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places"></script>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map-canvas, #map_canvas {
height: 100%;
}
@media print {
html, body {
height: auto;
}
#map_canvas {
height: 650px;
}
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
input {
border: 1px solid rgba(0, 0, 0, 0.5);
}
input.notfound {
border: 2px solid rgba(255, 0, 0, 0.4);
}
</style>
<script>
// <![CDATA[
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-33.8688, 151.2195),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var input = /** @type {HTMLInputElement} */(document.getElementById('searchTextField'));
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', map);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map
});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
marker.setVisible(false);
input.className = '';
var place = autocomplete.getPlace();
if (!place.geometry) {
// Inform the user that the place was not found and return.
input.className = 'notfound';
return;
}
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setIcon(/** @type {google.maps.Icon} */({
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(35, 35)
}));
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
// Sets a listener on a radio button to change the filter type on Places
// Autocomplete.
function setupClickListener(id, types) {
var radioButton = document.getElementById(id);
google.maps.event.addDomListener(radioButton, 'click', function() {
autocomplete.setTypes(types);
});
}
setupClickListener('changetype-all', []);
setupClickListener('changetype-establishment', ['establishment']);
setupClickListener('changetype-geocode', ['geocode']);
}
google.maps.event.addDomListener(window, 'load', initialize);
// ]]>
</script>
</h:head>
<h:body>
<div id="panel" style="margin-left: -260px">
<input id="searchTextField" type="text" size="50"></input>
<input type="radio" name="type" id="changetype-all" checked="checked"></input>
<label for="changetype-all">All</label>
<input type="radio" name="type" id="changetype-establishment"></input>
<label for="changetype-establishment">Establishments</label>
<input type="radio" name="type" id="changetype-geocode"></input>
<label for="changetype-geocode">Geocodes</label>
</div>
<div id="map-canvas"></div>
</h:body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With