From 1cfda9bb352f3a562599557ff5b88de42ee74278 Mon Sep 17 00:00:00 2001 From: Craig Kochis Date: Thu, 18 Jul 2024 16:45:52 -0400 Subject: [PATCH 1/2] add logic to cancel in-flight autocomplete requests to fix race condition --- src/api/search.ts | 3 ++- src/http.ts | 22 ++++++++++++++++++++++ src/ui/autocomplete.ts | 2 +- styles/radar.css | 3 +++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/api/search.ts b/src/api/search.ts index 24683c25..f404481d 100644 --- a/src/api/search.ts +++ b/src/api/search.ts @@ -12,7 +12,7 @@ import type { } from '../types'; class SearchAPI { - static async autocomplete(params: RadarAutocompleteParams): Promise { + static async autocomplete(params: RadarAutocompleteParams, requestId?: string): Promise { const options = Config.get(); let { @@ -45,6 +45,7 @@ class SearchAPI { expandUnits, mailable, }, + requestId, }); const autocompleteRes = { diff --git a/src/http.ts b/src/http.ts index b5b7cc5d..625276e6 100644 --- a/src/http.ts +++ b/src/http.ts @@ -25,6 +25,8 @@ interface HttpResponse { data: any; } +const inFlightRequests = new Map(); + class Http { static async request({ method, @@ -34,6 +36,7 @@ class Http { version, headers = {}, responseType, + requestId, }: { method: HttpMethod; path: string; @@ -42,6 +45,7 @@ class Http { version?: string; headers?: Record; responseType?: XMLHttpRequestResponseType; + requestId?: string; }) { return new Promise((resolve, reject) => { const options = Config.get(); @@ -79,9 +83,22 @@ class Http { body = undefined; // dont send body for GET request } + // check for in-flight requests with matching requestIds + if (requestId) { + const request = inFlightRequests.get(requestId); + if (request) { + request.abort(); // abort request + } + } + const xhr = new XMLHttpRequest(); xhr.open(method, url, true); + // save reference to request + if (requestId) { + inFlightRequests.set(requestId, xhr); + } + const defaultHeaders = { 'Authorization': publishableKey, 'Content-Type': 'application/json', @@ -109,6 +126,11 @@ class Http { xhr.onload = () => { let response: any; + + if (requestId) { // clear in-flight request + inFlightRequests.delete(requestId); + } + try { if (xhr.responseType === 'blob') { response = { code: xhr.status, data: xhr.response }; diff --git a/src/ui/autocomplete.ts b/src/ui/autocomplete.ts index 4e316ed9..bf761eee 100644 --- a/src/ui/autocomplete.ts +++ b/src/ui/autocomplete.ts @@ -263,7 +263,7 @@ class AutocompleteUI { onRequest(params); } - const { addresses } = await SearchAPI.autocomplete(params); + const { addresses } = await SearchAPI.autocomplete(params, 'autocomplete-ui'); return addresses; } diff --git a/styles/radar.css b/styles/radar.css index 5cb65b50..8cedf6a1 100644 --- a/styles/radar.css +++ b/styles/radar.css @@ -211,3 +211,6 @@ .maplibregl-ctrl-attrib.hidden { display: none !important; } +.maplibregl-popup-close-button:focus-visible { + outline: none; +} From f0dcb479014a530914186f992a3f7e3d6585ea64 Mon Sep 17 00:00:00 2001 From: Craig Kochis Date: Thu, 18 Jul 2024 17:01:09 -0400 Subject: [PATCH 2/2] disable browser autofill and prevent css changes on powered by --- src/ui/autocomplete.ts | 3 +++ styles/radar.css | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ui/autocomplete.ts b/src/ui/autocomplete.ts index bf761eee..837a631d 100644 --- a/src/ui/autocomplete.ts +++ b/src/ui/autocomplete.ts @@ -168,6 +168,9 @@ class AutocompleteUI { this.container.appendChild(this.wrapper); } + // disable browser autofill + this.inputField.setAttribute('autocomplete', 'off'); + // set aria roles this.inputField.setAttribute('role', 'combobox'); this.inputField.setAttribute('aria-controls', CLASSNAMES.RESULTS_LIST); diff --git a/styles/radar.css b/styles/radar.css index 8cedf6a1..723a907c 100644 --- a/styles/radar.css +++ b/styles/radar.css @@ -185,12 +185,12 @@ } .radar-powered a { - text-decoration: none; - color: var(--radar-gray6); + text-decoration: none !important; + color: var(--radar-gray6) !important; } .radar-powered a:visited { - color: var(--radar-gray6); + color: var(--radar-gray6) !important; } .radar-powered #radar-powered-logo {