Skip to content

Instantly share code, notes, and snippets.

@xlplugins
Last active June 6, 2026 06:11
Show Gist options
  • Select an option

  • Save xlplugins/56a3eb69739156fcad121b113be634a7 to your computer and use it in GitHub Desktop.

Select an option

Save xlplugins/56a3eb69739156fcad121b113be634a7 to your computer and use it in GitHub Desktop.
Fix Google Map Auto Complete On Reload
add_action('wp_footer', function () {
if ( ! function_exists('is_checkout') || ! is_checkout() ) return;
?>
<script>
(function ($) {
var attached = { billing: false, shipping: false };
function ready() {
return window.google && google.maps && google.maps.places;
}
function isVisible(el) {
// fast & reliable for mobile (works while keyboard is showing)
return el && el.offsetParent !== null;
}
function getCountry(prefix) {
var c = $('#' + prefix + '_country').val();
return c ? c.toLowerCase() : null;
}
function attach(prefix) {
if (attached[prefix]) return true;
if (!ready()) return false;
var input = document.querySelector('#' + prefix + '_address_1');
if (!input) return false;
if (!isVisible(input)) return false; // never attach to a hidden input
if (input.classList.contains('pac-target-input')) {
attached[prefix] = true;
return true;
}
try {
var opts = { types: ['address'] };
var country = getCountry(prefix);
if (country) opts.componentRestrictions = { country: country };
new google.maps.places.Autocomplete(input, opts);
attached[prefix] = true;
return true;
} catch (e) {
return false;
}
}
function attachAll() {
attach('billing');
attach('shipping');
}
function pollAttach() {
var tries = 0;
var t = setInterval(function () {
tries++;
attachAll();
if ((attached.billing && attached.shipping) || tries > 40) {
clearInterval(t);
}
}, 250);
}
// =====================================================================
// Keep the WHOLE address (billing + a different shipping) across a plain
// =====================================================================
var STORE = 'fk_addr_v1';
var FIELDS = ['first_name', 'last_name', 'company', 'country', 'state', 'address_1', 'address_2', 'city', 'postcode', 'phone'];
var PFX = ['billing', 'shipping'];
var isRestoring = false;
var userInteracted = false; // once the customer edits, stop auto-restoring so we never fight them
function eachField(cb) {
PFX.forEach(function (p) { FIELDS.forEach(function (f) { cb(p + '_' + f); }); });
}
function saveAll() {
if (isRestoring) return;
var d = {};
eachField(function (id) {
var $f = $('#' + id);
if ($f.length) { var v = $f.val(); if (v != null && v !== '') d[id] = v; }
});
var cb = document.getElementById('ship-to-different-address-checkbox');
if (cb) d.__ship = cb.checked ? 1 : 0;
try { sessionStorage.setItem(STORE, JSON.stringify(d)); } catch (e) {}
}
// Set a value WITHOUT firing WC's plain 'change' (which would loop update_checkout);
// 'change.select2' keeps the state/country dropdowns visually in sync.
function setSilently($f, v) {
if (!$f.length || v == null || $f.val() === v) return;
$f.val(v);
if ($f.is('select')) {
$f.trigger('change.select2'); // keep the select2 display in sync (no update_checkout)
} else {
$f.trigger('keyup').trigger('focusout');
}
}
function applyStored(d) {
// Country first (so the state dropdown has its options), then the rest, then state.
PFX.forEach(function (p) { setSilently($('#' + p + '_country'), d[p + '_country']); });
eachField(function (id) {
if (/_(country|state)$/.test(id)) return;
if (typeof d[id] !== 'undefined') setSilently($('#' + id), d[id]);
});
PFX.forEach(function (p) { setSilently($('#' + p + '_state'), d[p + '_state']); });
}
// True once every stored TEXT field actually holds its value. We don't gate on
// country/state/phone — select2 + intl-tel reformat their values, so a strict compare
// would never match and we'd retry forever.
function allStoredApplied(d) {
var ok = true;
eachField(function (id) {
if (typeof d[id] === 'undefined' || /_(country|state|phone)$/.test(id)) return;
var $f = $('#' + id);
if (!$f.length || $f.val() !== d[id]) ok = false;
});
return ok;
}
function restoreAll() {
var raw; try { raw = sessionStorage.getItem(STORE); } catch (e) { return; }
if (!raw) return;
var d; try { d = JSON.parse(raw); } catch (e) { return; }
isRestoring = true;
// Re-check "ship to a different address" if it was, so the shipping fields exist.
var $cb = $('#ship-to-different-address-checkbox');
if ($cb.length && typeof d.__ship !== 'undefined') {
var want = d.__ship == 1;
if ($cb.is(':checked') !== want) { $cb.prop('checked', want).trigger('change'); }
}
// Apply now and keep retrying for ~2.5s. Shipping fields (especially shipping_address_1
// and shipping_city) can render late or get cleared by the autocomplete on slower live
// loads; retrying guarantees they ALWAYS end up filled. Stops early once the customer
// starts editing so we never fight them.
var attempts = 0;
(function tryApply() {
if (userInteracted) { isRestoring = false; return; }
applyStored(d);
attempts++;
if ((allStoredApplied(d) && attempts >= 2) || attempts >= 10) {
isRestoring = false;
} else {
setTimeout(tryApply, 250);
}
})();
}
$(function () {
restoreAll(); // runs on full page load (F5) — this is the key bit
pollAttach();
});
$(document.body).on('input', '#wfacp_checkout_form input, form.checkout input', function (e) {
if (e.originalEvent) userInteracted = true;
if (userInteracted && !isRestoring) saveAll();
});
$(document.body).on('change', '#wfacp_checkout_form input, #wfacp_checkout_form select, form.checkout input, form.checkout select', function (e) {
if (e.originalEvent) userInteracted = true;
if (userInteracted && !isRestoring) saveAll();
});
// AJAX refresh: re-attach autocomplete. Only re-apply saved values UNTIL the customer
// starts editing — after that, never restore, so we don't snap their changes back.
$(document.body).on('updated_checkout wfacp_updated_checkout wfacp_form_updated', function () {
if (!attached.billing || !attached.shipping) { pollAttach(); }
if (!userInteracted) restoreAll();
});
// Ship-to-different toggled: re-attach autocomplete to the now-visible shipping input.
$(document.body).on('change', '#ship-to-different-address-checkbox', function (e) {
if ($(this).is(':checked')) {
attached.shipping = false;
setTimeout(pollAttach, 700);
}
if (e.originalEvent) userInteracted = true;
if (userInteracted && !isRestoring) saveAll();
});
})(jQuery);
</script>
<?php
}, 300 );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment