From 1ebf7db3faa8a2be1d35347407a365f5cf3004de Mon Sep 17 00:00:00 2001 From: Nayden Naydenov <31909318+nnaydenow@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:06:39 +0300 Subject: [PATCH] fix(f6 navigation): work properly when multiple runtimes (#9810) F6 navigation adds `keydown` handler to the body element that will move the focus to the previous / next group that has focusable element. If F6 navigation feature is enabled in multiple runtimes this handler will be attach multiple times. With current change, we ensure that only one callback will be executed to move the focus to the correct element. This callback is coming from the latest registered runtime (newest version). Fixes: https://github.com/SAP/ui5-webcomponents/issues/9795 --- packages/base/src/features/F6Navigation.ts | 39 +++++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/base/src/features/F6Navigation.ts b/packages/base/src/features/F6Navigation.ts index a8f0e819d0b2..a67b65eb95c2 100644 --- a/packages/base/src/features/F6Navigation.ts +++ b/packages/base/src/features/F6Navigation.ts @@ -4,9 +4,23 @@ import { instanceOfUI5Element } from "../UI5Element.js"; import { getFirstFocusableElement } from "../util/FocusableElements.js"; import getFastNavigationGroups from "../util/getFastNavigationGroups.js"; import isElementClickable from "../util/isElementClickable.js"; +import { getCurrentRuntimeIndex, compareRuntimes } from "../Runtimes.js"; +import getSharedResource from "../getSharedResource.js"; + +type F6Registry = { + instance?: F6Navigation, +} + +const currentRuntimeINdex = getCurrentRuntimeIndex(); + +const shouldUpdate = (runtimeIndex: number | undefined) => { + if (runtimeIndex === undefined) { + return true; + } + return compareRuntimes(currentRuntimeINdex, runtimeIndex) === 1; // 1 means the current is newer, 0 means the same, -1 means the resource's runtime is newer +}; class F6Navigation { - static _instance: F6Navigation; keydownHandler: (event: KeyboardEvent) => void; selectedGroup: HTMLElement | null = null; groups: Array = []; @@ -20,6 +34,10 @@ class F6Navigation { document.addEventListener("keydown", this.keydownHandler); } + removeEventListeners() { + document.removeEventListener("keydown", this.keydownHandler); + } + async groupElementToFocus(nextElement: HTMLElement) { const nextElementDomRef = instanceOfUI5Element(nextElement) ? nextElement.getDomRef() : nextElement; @@ -149,10 +167,6 @@ class F6Navigation { elementToFocus?.focus(); } - removeEventListeners() { - document.removeEventListener("keydown", this.keydownHandler); - } - updateGroups() { this.setSelectedGroup(); this.groups = getFastNavigationGroups(document.body); @@ -181,12 +195,19 @@ class F6Navigation { this.removeEventListeners(); } + get _ui5RuntimeIndex() { + return currentRuntimeINdex; + } + static init() { - if (!this._instance) { - this._instance = new F6Navigation(); - } + const f6Registry = getSharedResource("F6Registry", {}); - return this._instance; + if (!f6Registry.instance) { + f6Registry.instance = new F6Navigation(); + } else if (shouldUpdate(f6Registry.instance?._ui5RuntimeIndex)) { + f6Registry.instance?.destroy(); + f6Registry.instance = new F6Navigation(); + } } }