From fc610d3e597127932551d37d27b6983bcd5f12ee Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 2 Aug 2026 14:58:59 +0200 Subject: [PATCH] Add a go to first/last menu-item helper method in the `Menu` class This fixes a bug when using the Home and End keyboard shortcuts to navigate through a `Menu` instance. These two buttons didn't update the `#lastIndex` field, which means that e.g. a following ArrowDown or ArrowUp press could make focus "jump" to an unexpected menu-item. Also, the helper method reduces a little bit of code duplication in the event handlers. --- web/menu.js | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/web/menu.js b/web/menu.js index 9861c7377..501325ef5 100644 --- a/web/menu.js +++ b/web/menu.js @@ -146,19 +146,11 @@ class Menu { stopEvent(e); break; case "Home": - this.#menuItems - .find( - item => !item.disabled && !item.classList.contains("hidden") - ) - ?.focus(); + this.#goToFirstLast(false); stopEvent(e); break; case "End": - this.#menuItems - .findLast( - item => !item.disabled && !item.classList.contains("hidden") - ) - ?.focus(); + this.#goToFirstLast(true); stopEvent(e); break; default: @@ -194,11 +186,7 @@ class Menu { if (!this.#openMenuAC) { this.#openMenu(); } - this.#menuItems - .find( - item => !item.disabled && !item.classList.contains("hidden") - ) - ?.focus(); + this.#goToFirstLast(false); break; case "ArrowUp": case "End": @@ -206,11 +194,7 @@ class Menu { if (!this.#openMenuAC) { this.#openMenu(); } - this.#menuItems - .findLast( - item => !item.disabled && !item.classList.contains("hidden") - ) - ?.focus(); + this.#goToFirstLast(true); break; case "Escape": this.#closeMenu(); @@ -252,6 +236,20 @@ class Menu { } } + /** + * Go to the first/last menu item. + * @param {boolean} [last] + */ + #goToFirstLast(last = false) { + const i = this.#menuItems[last ? "findLastIndex" : "findIndex"]( + item => !item.disabled && !item.classList.contains("hidden") + ); + if (i >= 0) { + this.#menuItems[i].focus(); + this.#lastIndex = i; + } + } + destroy() { this.#closeMenu(); this.#menuAC?.abort();