Last active
June 6, 2026 06:11
-
-
Save xlplugins/56a3eb69739156fcad121b113be634a7 to your computer and use it in GitHub Desktop.
Fix Google Map Auto Complete On Reload
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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