SureForms is quite new and does not yet support Google address auto suggestions (Address AutoSuggest) or Auto Complete (however you remember it).
We have developed a code-snippet that’ll ensure things “just work”.
You will need to replace APIKEYHERE with your own Google Places API key
Places API V2 and Places API V1 available
Google Places APIV2 – JS Snippet
This one adds its own Google Places Styling – Depending on your use-case you may prefer this as it finds “more”.
/* SureForms Google Places (AU) — new widget + legacy fallback, multi-field */
(() => {
'use strict';
// === EDIT THESE SELECTORS (recommended) ===
// Example: ['input[name="from_address"]','input[name="to_address"]']
const SELECTORS = [];
// === Your API key (restrict by HTTP referrer) ===
const API_KEY = 'APIKEYHERE';
const MAPS_SRC =
'https://maps.googleapis.com/maps/api/js?key=' +
encodeURIComponent(API_KEY) +
'&v=weekly&loading=async&libraries=places';
const STATE_MAP = {
'New South Wales':'NSW','NSW':'NSW',
'Victoria':'VIC','VIC':'VIC',
'Queensland':'QLD','QLD':'QLD',
'South Australia':'SA','SA':'SA',
'Western Australia':'WA','WA':'WA',
'Tasmania':'TAS','TAS':'TAS',
'Northern Territory':'NT','NT':'NT',
'Australian Capital Territory':'ACT','ACT':'ACT'
};
if (window.v8SureFormsPlacesInit) return;
window.v8SureFormsPlacesInit = true;
// Make the new element inherit colours
const style = document.createElement('style');
style.textContent = `
gmpx-place-autocomplete, gmpx-place-autocomplete * { color: inherit; }
gmpx-place-autocomplete { width: 100%; display:block; }
`;
document.head.appendChild(style);
function explicitInputs() {
if (!SELECTORS.length) return [];
const out = [];
SELECTORS.forEach(sel => document.querySelectorAll(sel).forEach(el => out.push(el)));
return out;
}
function autoInputs() {
return Array.from(
document.querySelectorAll(
// Be generous: SureForms/Blocksy variations
'.srfm-address-block input.srfm-input-input,' +
'.srfm-input-block input.srfm-input-input,' +
'.srfm-block-single input[type="text"],' +
'form input[type="text"].srfm-input-input'
)
);
}
function uniq(arr) {
const s = new Set();
const out = [];
for (const el of arr) if (el && !s.has(el)) { s.add(el); out.push(el); }
return out;
}
function targetInputs() {
const explicit = explicitInputs();
if (explicit.length) return uniq(explicit);
// fallback to auto
return uniq(autoInputs());
}
function findAddressBlock(el){
return el.closest('.srfm-address-block') ||
el.closest('.srfm-input-block') ||
el.closest('.srfm-block-single') ||
el.parentElement;
}
async function mountNewWidget(originalInput){
if (!google?.maps?.places?.PlaceAutocompleteElement) return false;
if (originalInput.dataset.v8PlacesReady) return true;
originalInput.dataset.v8PlacesReady = '1';
const pac = new google.maps.places.PlaceAutocompleteElement();
pac.includedRegionCodes = ['au'];
pac.setAttribute('placeholder', originalInput.getAttribute('placeholder') || 'Start typing your address');
const block = findAddressBlock(originalInput);
originalInput.parentNode.insertBefore(pac, originalInput);
// Hide original but keep it in form
Object.assign(originalInput.style, { position:'absolute', left:'-9999px', width:'1px', height:'1px' });
originalInput.setAttribute('aria-hidden','true');
originalInput.tabIndex = -1;
// Mirror typing
pac.addEventListener('input', () => {
originalInput.value = pac.value || '';
originalInput.dispatchEvent(new Event('input', { bubbles: true }));
});
async function applyPlace(place){
try { await place.fetchFields({ fields: ['formattedAddress','addressComponents'] }); } catch(e){}
if (place.formattedAddress) {
originalInput.value = place.formattedAddress;
originalInput.dispatchEvent(new Event('input', { bubbles: true }));
originalInput.dispatchEvent(new Event('change', { bubbles: true }));
}
// Auto state
const stateSelect = block ? block.querySelector('select.srfm-dropdown-input') : null;
if (stateSelect && Array.isArray(place.addressComponents)) {
let stateText = '';
for (const c of place.addressComponents) {
if (c.types && c.types.indexOf('administrative_area_level_1') !== -1) {
stateText = (c.shortText || c.longText || '').trim();
break;
}
}
if (stateText) {
const abbr = STATE_MAP[stateText] || stateText;
setTimeout(() => {
if (stateSelect.tomselect && typeof stateSelect.tomselect.setValue === 'function') {
stateSelect.tomselect.setValue(abbr, true);
} else {
stateSelect.value = abbr;
stateSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
}, 100);
}
}
}
pac.addEventListener('gmp-select', async (ev) => {
const pred = ev.placePrediction;
if (pred && pred.toPlace) await applyPlace(pred.toPlace());
});
pac.addEventListener('gmp-placeselect', async (ev) => {
if (ev.place) await applyPlace(ev.place);
});
return true;
}
function mountLegacy(input){
if (!google?.maps?.places?.Autocomplete) return false;
if (input.dataset.v8PlacesReady) return true;
input.dataset.v8PlacesReady = '1';
const ac = new google.maps.places.Autocomplete(input, {
componentRestrictions: { country: 'au' },
fields: ['address_components','formatted_address'],
types: ['address']
});
ac.addListener('place_changed', () => {
const place = ac.getPlace();
if (!place || !place.address_components) return;
input.value = place.formatted_address || input.value;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
const block = findAddressBlock(input);
const stateSelect = block ? block.querySelector('select.srfm-dropdown-input') : null;
if (!stateSelect) return;
let state = '';
place.address_components.forEach((c) => {
if ((c.types || [])[0] === 'administrative_area_level_1') {
state = c.short_name || c.long_name || '';
}
});
if (!state) return;
const abbr = STATE_MAP[state] || state;
setTimeout(() => {
if (stateSelect.tomselect && typeof stateSelect.tomselect.setValue === 'function') {
stateSelect.tomselect.setValue(abbr, true);
} else {
stateSelect.value = abbr;
stateSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
}, 100);
});
return true;
}
function mountAll() {
const inputs = targetInputs();
inputs.forEach(async (el) => {
// Try new widget first; fallback to legacy if missing
const ok = await mountNewWidget(el);
if (!ok) mountLegacy(el);
});
}
function afterMapsReady(){
// First pass
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', mountAll);
} else {
mountAll();
}
// Late-loaded steps/sections
const mo = new MutationObserver(() => mountAll());
try { mo.observe(document.body, { childList: true, subtree: true }); } catch(e){}
}
// Load Maps once (if already on page, we just proceed)
function ensureMaps(callback){
if (window.google && google.maps) {
// places lib already loaded because we added &libraries=places
callback();
return;
}
if (document.querySelector('script[src^="https://maps.googleapis.com/maps/api/js"]')) {
const t = setInterval(() => {
if (window.google && google.maps) { clearInterval(t); callback(); }
}, 80);
return;
}
const s = document.createElement('script');
s.src = MAPS_SRC; s.async = true; s.defer = true;
s.onload = callback;
s.onerror = () => setTimeout(() => ensureMaps(callback), 200);
document.head.appendChild(s);
}
ensureMaps(afterMapsReady);
})();
Places API V1 – PHP Snippet
This one is the legacy version – but does not add styling
<?php
/**
* Google Places Autocomplete for SureForms
*/
function sureforms_google_places_integration() {
// Replace with your Google Places API Key
$api_key = 'APIKEYHERE';
if (is_admin()) return;
// Enqueue Google Places API
wp_enqueue_script('google-places-api',
'https://maps.googleapis.com/maps/api/js?key=' . $api_key . '&libraries=places',
array(), null, true);
// Add inline JavaScript
wp_add_inline_script('google-places-api', "
(function() {
'use strict';
// Global namespace to prevent multiple initializations
if (window.sureForms_places_initialized) {
return;
}
window.sureForms_places_initialized = true;
const config = {
country: 'au',
stateMapping: {
'New South Wales': 'NSW', 'NSW': 'NSW',
'Australian Capital Territory': 'ACT', 'ACT': 'ACT',
'Queensland': 'QLD', 'QLD': 'QLD',
'Victoria': 'VIC', 'VIC': 'VIC',
'South Australia': 'SA', 'SA': 'SA',
'Northern Territory': 'NT', 'NT': 'NT',
'Western Australia': 'WA', 'WA': 'WA',
'Tasmania': 'TAS', 'TAS': 'TAS'
}
};
function setupAutocomplete(addressInput, stateSelect) {
// Skip if already initialized
if (addressInput.getAttribute('data-places-ready')) {
return;
}
addressInput.setAttribute('data-places-ready', '1');
const autocomplete = new google.maps.places.Autocomplete(addressInput, {
componentRestrictions: { country: config.country },
fields: ['address_components', 'formatted_address'],
types: ['address']
});
autocomplete.addListener('place_changed', function() {
const place = autocomplete.getPlace();
if (!place.address_components) return;
let state = '';
place.address_components.forEach(function(c) {
if (c.types[0] === 'administrative_area_level_1') {
state = c.short_name;
}
});
addressInput.value = place.formatted_address;
if (state && stateSelect) {
const stateAbbr = config.stateMapping[state] || state;
setTimeout(function() {
if (stateSelect.tomselect) {
stateSelect.tomselect.setValue(stateAbbr, true);
}
}, 150);
}
});
}
function initFields() {
if (typeof google === 'undefined' || !google.maps || !google.maps.places) {
return;
}
const blocks = document.querySelectorAll('.srfm-address-block');
blocks.forEach(function(block) {
const input = block.querySelector('input.srfm-input-input');
const select = block.querySelector('select.srfm-dropdown-input');
if (input) {
setupAutocomplete(input, select);
}
});
}
// Wait for Google API and DOM
function tryInit() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
setTimeout(initFields, 500);
});
} else {
setTimeout(initFields, 500);
}
}
tryInit();
})();
");
}
add_action('wp_enqueue_scripts', 'sureforms_google_places_integration');


