From df795fe894c2d163c6114aceecbdbc765ce30932 Mon Sep 17 00:00:00 2001 From: DarkWiiPlayer Date: Thu, 16 Jan 2025 16:16:56 +0100 Subject: [PATCH] Implement quick search in closed selects --- package.json | 2 +- src/BetterSelect.js | 65 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index b75a340..7a9b7e1 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,6 @@ "browser": "src/BetterSelect.js", "type": "module", "license": "MIT", - "version": "1.2.2", + "version": "1.3.0", "url": "https://darkwiiplayer.github.io/BetterSelect/" } diff --git a/src/BetterSelect.js b/src/BetterSelect.js index 9dbec02..7ec200e 100644 --- a/src/BetterSelect.js +++ b/src/BetterSelect.js @@ -191,14 +191,30 @@ export class BetterSelect extends HTMLElement { }) this.addEventListener("keydown", event => { - if (event.key == " " && this.list.contains(this.shadowRoot.activeElement)) { - if (this.#internals.states.has("--open")) { + const key = event.key + if (this.#internals.states.has("--open")) { + if (key == " " && this.list.contains(this.shadowRoot.activeElement)) { + this.close() + event.preventDefault() + event.stopPropagation() + } else if (key == "Escape") { this.close() - } else { - this.open() } - } else if (event.key == "Escape") { - this.close() + } else { + if (key == " ") { + this.open() + } else if (key == "Escape") { + this.keyboardSearchBuffer = "" + event.preventDefault() + event.stopPropagation() + } else if (key == "Backspace") { + event.preventDefault() + event.stopPropagation() + } else if (!event.ctrlKey && !event.altKey && key.match(/^[a-zA-Z0-9]$/)) { + this.keyboardSearchAppend(key) + event.preventDefault() + event.stopPropagation() + } } }) @@ -211,6 +227,39 @@ export class BetterSelect extends HTMLElement { }) } + /** + * @param {String} key + */ + keyboardSearchAppend(key) { + this.searchTimeout?.abort() + this.searchTimeout = new AbortController() + + const timeout = 1000 * (Number(this.getAttribute("search-timeout")) || 1) + const ref = setTimeout(()=> { + console.warn("Clearing buffer: " + this.keyboardSearchBuffer) + this.keyboardSearchBuffer = "" + }, timeout) + this.searchTimeout.signal.addEventListener("abort", () => { + window.clearTimeout(ref) + }) + + this.keyboardSearchBuffer = (this.keyboardSearchBuffer || "") + key + + this.closedSearch(this.keyboardSearchBuffer) + } + + /** + * @param {string} search + */ + closedSearch(search) { + for (const item of this.list.children) { + if (this.match(search, item)) { + this.setOption(item) + return + } + } + } + async open() { if (this.#abortOpen) return @@ -343,4 +392,8 @@ export class BetterSelect extends HTMLElement { } } } + + clear() { + this.setValue(undefined, "") + } }