Since I spent a few hours on this, I figured I'd give back to the community. Here is the JS you have to inject in the "Advanced" header section of the page with the form - this will need extra work if you have more than the form as an input field on the page and this is tailored for Canada but you get the idea. I make no apologies for the beginner code 🙂
<script>
let input_line = null
let componentForm = {
street_number: ['short_name', null],
route: ['long_name', null],
locality: ['long_name', null],
administrative_area_level_1: ['short_name', null],
country: ['long_name', null],
postal_code: ['short_name', null]
};
const options = {
componentRestrictions: { country: "ca" },
fields: ["address_components", "geometry", "icon", "name"],
strictBounds: false,
};
let line1 = null;
let line2 = null;
let city = null;
let state = null;
let zip = null;
let autocomplete = null
let mapsLibLoaded = false;
document.addEventListener ( 'DOMContentLoaded', ( ) => {
window.addEventListener('load', function(){
const selector2 = 'input[id*="address-"]';
const elements = document.querySelectorAll ( selector2 );
if (elements != null) {
Array.prototype.forEach.call(elements, function(element) {
console.log( " adding a listener to " + element.id)
if (element.id.includes("line1")) line1 = element;
else if (element.id.includes("line2")) {
line2 = element;
line2.disabled = true
}
else if (element.id.includes("city")) {
city = element;
city.disabled = true;
}
else if (element.id.includes("state")) {
state = element;
state.disabled = true
}
else if (element.id.includes("zip")) {
zip = element;
zip.disabled = true
}
});
} else {
console.log("Didn't find the element");
}
//lazy load initialize google maps because the fields in sqarespace dont seem to exist before this.
let script = document.createElement('script');
script.onload = function() {
mapsLibLoaded = true;
};
script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&callback=initialize&key=<YOUR KEY HERE>";
document.head.appendChild(script);
} );
} );
function initialize() {
if (line1 != null) {
console.log("Loading google");
autocomplete = new google.maps.places.Autocomplete(line1, options);
autocomplete.addListener('place_changed', fillInAddress);
} else {
console.log("Unable to load google");
}
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
if (place == null) {
console.log("No place");
return;
}
//don't bother clearing value since this is managed by react
line1.disabled = false;
line2.disabled = false;
city.disabled = false;
state.disabled = false;
zip.disabled = false;
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType][0]];
console.log("Found " + componentForm[addressType][0] + " " + val)
componentForm[addressType][1] = val
}
}
var street_num = componentForm['street_number'][1]; //street number
var street_name = componentForm['route'][1]; //route
var city_name = componentForm['locality'][1]; //locality
var province_name = componentForm['administrative_area_level_1'][1]; //admin region
var postal_code = componentForm['postal_code'][1]; //post code
//Remove the listener while we update the component via react. You only get one chance since i'm not sure how to add again...
google.maps.event.clearInstanceListeners(line1);
set_value(line1, street_num + " " + street_name);
set_value(city, city_name);
set_value(state, province_name);
set_value(zip, postal_code);
autocomplete = new google.maps.places.Autocomplete(line1, options);
autocomplete.addListener('place_changed', fillInAddress);
}
function set_value(component, value_string) {
//Deal with React shenanigans
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(component, value_string);
var inputEvent = new Event('input', { bubbles: true});
component.dispatchEvent(inputEvent);
}
</script>