Dynamic Autocomplete Configuration Number of autocomplete sections: 2 Section 1 Name: Billing Allowed States: CA Section 2 Name: Mailing Allowed States: CA const autocompleteConfig = [ { "autocompleteInputId": "billing_ac", "ALLOWED_STATES": [ "CA" ], "ADDRESS_INPUT_IDS": { "street": "billing-street_ac", "city": "billing-city_ac", "zip": "billing-zip_ac", "state": "billing-state_ac", "county": "billing-county_ac", "apt": "billing-apt_ac" } }, { "autocompleteInputId": "mailing_ac", "ALLOWED_STATES": [ "CA" ], "ADDRESS_INPUT_IDS": { "street": "mailing-street_ac", "city": "mailing-city_ac", "zip": "mailing-zip_ac", "state": "mailing-state_ac", "county": "mailing-county_ac", "apt": "mailing-apt_ac" } } ]; injectCSS(autocompleteConfig); var SESSION_TOKEN = getUUIDv4(); var API_ENDPOINT = 'https://n8n.civiq.io/webhook/auto6a66eb68-b3c0-45dd-a930-8cf43ef28570?session_token=' + SESSION_TOKEN; var observer; document.addEventListener("DOMContentLoaded", function() { initializeAutocomplete(); observeFormChanges(); }); function observeFormChanges() { var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { initializeAutocomplete(); } }); }); observer.observe(document.body, { childList: true, subtree: true }); } function initializeAutocomplete() { autocompleteConfig.forEach(function(config) { var inputElement = document.querySelector('[aria-label="' + config.autocompleteInputId + '"]'); if (inputElement && !inputElement.classList.contains("autocomplete-initialized")) { console.log("creating autocomplete"); createAddressAutocomplete(config); injectCSS([config]); // Inject CSS for this config only if the element exists } }); } function createAddressAutocomplete(config) { var inputElement = document.querySelector('[aria-label="' + config.autocompleteInputId + '"]'); if (inputElement) { inputElement.classList.add("autocomplete-initialized"); var addressAutocomplete = new AddressAutocomplete({ ...config, API_ENDPOINT: API_ENDPOINT, }); } } class AddressAutocomplete { constructor(config) { this.config = config; this.dropdownElement = null; this.init(); } init() { this.inputElement = document.querySelector('[aria-label="' + this.config.autocompleteInputId + '"]'); if (!this.inputElement) return; this.createDropdownElement(); this.addEventListeners(); } createDropdownElement() { this.dropdownElement = document.createElement("div"); this.dropdownElement.id = "suggestions-dropdown"; this.dropdownElement.style.display = "none"; document.body.appendChild(this.dropdownElement); } addEventListeners() { this.inputElement.addEventListener( "input", this.debounce(this.fetchSuggestions.bind(this), 300) ); window.addEventListener("resize", this.repositionDropdown.bind(this)); document.addEventListener("click", function(event) { if ( !this.dropdownElement.contains(event.target) && event.target !== this.inputElement ) { this.dropdownElement.style.display = "none"; } }.bind(this)); } async fetchSuggestions(e) { var value = e.target.value; if (!value) { this.dropdownElement.style.display = "none"; return; } try { var response = await fetch( this.config.API_ENDPOINT + '&input=' + encodeURIComponent(value) ); console.log("Fetching suggestions"); if (!response.ok) throw new Error("Failed to fetch"); var suggestions = await response.json(); var filteredSuggestions = suggestions.filter(function(suggestion) { return this.config.ALLOWED_STATES?.includes(suggestion.state); }.bind(this)); this.updateDropdown(filteredSuggestions); } catch (error) { console.error("Error fetching address suggestions:", error); this.dropdownElement.style.display = "none"; } } updateDropdown(suggestions) { this.dropdownElement.innerHTML = ""; suggestions.forEach(function(suggestion) { var div = document.createElement("div"); div.className = "suggestion-item"; var addressLine = '
' + suggestion.street + ', ' + suggestion.city + ', ' + suggestion.state + ' ' + suggestion.zip + '
'; div.innerHTML = addressLine; div.addEventListener("click", function() { this.selectAddress(suggestion); }.bind(this)); this.dropdownElement.appendChild(div); }.bind(this)); this.dropdownElement.style.display = suggestions.length > 0 ? "block" : "none"; this.repositionDropdown(); } selectAddress(suggestion) { toggleCSSVisibility(); sessionStorage.setItem("selectedAddress", JSON.stringify(suggestion)); this.setValue( this.inputElement, suggestion.street + ', ' + suggestion.city + ', ' + suggestion.state + ' ' + suggestion.zip ); this.fillAddressFields(suggestion); this.dropdownElement.style.display = "none"; } fillAddressFields(suggestion) { var addressInputIds = this.config.ADDRESS_INPUT_IDS; var lastInputElement = null; if (addressInputIds) { for (var key in addressInputIds) { var selector = addressInputIds[key]; var inputElement = document.querySelector('[aria-label="' + selector + '"]'); if (inputElement) { this.setValue(inputElement, suggestion[key] || ""); lastInputElement = inputElement; } } if (lastInputElement) { lastInputElement.focus(); lastInputElement.value = ""; } } } repositionDropdown() { var rect = this.inputElement.getBoundingClientRect(); this.dropdownElement.style.top = (rect.bottom + window.scrollY) + 'px'; this.dropdownElement.style.left = (rect.left + window.scrollX) + 'px'; this.dropdownElement.style.width = rect.width + 'px'; } setValue(inputElement, newValue) { var nativeInputValueSetter = Object.getOwnPropertyDescriptor( window.HTMLInputElement.prototype, "value" ).set; nativeInputValueSetter.call(inputElement, newValue); inputElement.dispatchEvent(new Event("change", { bubbles: true })); } debounce(func, delay) { var debounceTimer; return function() { var args = arguments; clearTimeout(debounceTimer); debounceTimer = setTimeout(function() { func.apply(this, args); }.bind(this), delay); }.bind(this); } } function getUUIDv4() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { var r = (Math.random() * 16) | 0, v = c === 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } function injectCSS(config) { var style = document.getElementById('custom-hide-style'); if (!style) { style = document.createElement('style'); style.id = 'custom-hide-style'; document.head.appendChild(style); // Append the style element immediately to the head } // Clear previous styles if any, to avoid duplication style.textContent = ''; config.forEach(function(configItem) { Object.values(configItem.ADDRESS_INPUT_IDS).forEach(function(id) { var elementExists = document.querySelector('[aria-label="' + id + '"]'); if (elementExists) { style.textContent += '.tally-column:has([aria-label="' + id + '"]) { display: none; } '; style.textContent += '.tally-column:has([aria-label="' + id + '"]) + .tally-column { display: none; } '; } }); }); } // Call this function when you want to toggle the visibility based on the injected CSS function toggleCSSVisibility() { var styleSheet = document.getElementById('custom-hide-style'); if (styleSheet) { styleSheet.disabled = !styleSheet.disabled; } }
Page 1 of 1

AC test 1

This is a test