diff --git a/package-lock.json b/package-lock.json index 92f02483..fca2b502 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "radar-sdk-js", - "version": "4.4.6-beta.1", + "version": "4.4.8", "license": "ISC", "dependencies": { "@types/geojson": "^7946.0.10" diff --git a/src/ui/autocomplete.ts b/src/ui/autocomplete.ts index aa090e25..b42fd2d0 100644 --- a/src/ui/autocomplete.ts +++ b/src/ui/autocomplete.ts @@ -75,6 +75,8 @@ class AutocompleteUI { highlightedIndex: number; debouncedFetchResults: (...args: any[]) => Promise; near?: string; + // ADDED: Cache for storing results by query + private resultsCache: Map = new Map(); // DOM elements container: HTMLElement; @@ -182,8 +184,10 @@ class AutocompleteUI { // setup event listeners this.inputField.addEventListener('input', this.handleInput.bind(this)); this.inputField.addEventListener('keydown', this.handleKeyboardNavigation.bind(this)); + this.inputField.addEventListener('focus', this.handleFocus.bind(this)); + // Handle blur to hide results, unless clicking on results if (this.config.hideResultsOnBlur) { - this.inputField.addEventListener('blur', this.close.bind(this), true); + this.inputField.addEventListener('blur', this.handleBlur.bind(this), true); } Logger.debug('AutocompleteUI initialized with options', this.config); @@ -192,17 +196,38 @@ class AutocompleteUI { public handleInput() { // Fetch autocomplete results and display them const query = this.inputField.value; + + // CHANGED: Clear results immediately if query is too short if (query.length < this.config.minCharacters) { + this.clearResultsList(); + this.close(); + return; + } + + // ADDED: Check cache first + const cachedResults = this.resultsCache.get(query); + if (cachedResults) { + const onResults = this.config.onResults; + if (onResults) { + onResults(cachedResults); + } + this.displayResults(cachedResults); return; } this.debouncedFetchResults(query) .then((results: any[]) => { - const onResults = this.config.onResults; - if (onResults) { - onResults(results); + // ADDED: Only display results if the query still matches current input + if (query === this.inputField.value) { + // ADDED: Cache the results + this.resultsCache.set(query, results); + + const onResults = this.config.onResults; + if (onResults) { + onResults(results); + } + this.displayResults(results); } - this.displayResults(results); }) .catch((error) => { Logger.warn(`Autocomplete ui error: ${error.message}`); @@ -213,6 +238,38 @@ class AutocompleteUI { }); } + + + // Add the handleFocus method + public handleFocus() { + if (this.inputField.value.length >= this.config.minCharacters && this.results.length > 0) { + this.displayResults(this.results); // Redisplay previous results + } + } + + // Update the blur handler to ensure it does not prematurely clear results + public handleBlur(event: FocusEvent) { + const relatedTarget = event.relatedTarget as HTMLElement; + const isClickOnResults = relatedTarget && this.resultsList.contains(relatedTarget); + + if (!isClickOnResults) { + this.close(); + } + } + + // CHANGED: Don't clear results, just hide them + public close() { + if (!this.isOpen) { + return; + } + + this.inputField.setAttribute('aria-expanded', 'false'); + this.inputField.setAttribute('aria-activedescendant', ''); + this.resultsList.setAttribute('hidden', ''); + this.highlightedIndex = -1; + this.isOpen = false; + } + public debounce(fn: Function, delay: number) { let timeoutId: any; let resolveFn: any; @@ -357,24 +414,6 @@ class AutocompleteUI { this.isOpen = true; } - public close(e?: FocusEvent) { - if (!this.isOpen) { - return; - } - - // run this code async to allow link click to propagate before blur - // (add 100ms delay if closed from link click) - const linkClick = e && (e.relatedTarget === this.poweredByLink); - setTimeout(() => { - this.inputField.setAttribute('aria-expanded', 'false'); - this.inputField.setAttribute('aria-activedescendant', ''); - this.resultsList.setAttribute('hidden', ''); - this.highlightedIndex = -1; - this.isOpen = false; - this.clearResultsList(); - }, linkClick ? 100 : 0); - } - public goTo(index: number) { if (!this.isOpen || !this.results.length) { return; @@ -603,4 +642,4 @@ class AutocompleteUI { } } -export default AutocompleteUI; +export default AutocompleteUI; \ No newline at end of file