diff --git a/src/lib/workersFocus.js b/src/lib/workersFocus.js index 3c850c7..4aac278 100644 --- a/src/lib/workersFocus.js +++ b/src/lib/workersFocus.js @@ -21,10 +21,12 @@ export function activeControl(doc) { const usable = (el) => Boolean(el) && typeof el === 'object' && typeof el.focus === 'function' && el.isConnected !== false && el.disabled !== true // Gibt den Fokus an den ersten brauchbaren Kandidaten (eingehängt, nicht gesperrt), falls er verloren ging. Ergebnis: ob fokussiert wurde. +// preventScroll: fokussiert focus() ohne die Option, springt die Seite zum Ziel; bei einer Zeile weit unten in einer langen Liste würde sie +// zur Meldung oben springen und die Person verlöre ihre Stelle. Der Fokus (und damit die Ansage) wandert, die Ansicht bleibt stehen. export function restoreFocus(doc, candidates) { if (!focusLost(doc)) return false const target = candidates.find(usable) if (!target) return false - target.focus() + target.focus({ preventScroll: true }) return true } diff --git a/tests/unit/workersFocus.test.mjs b/tests/unit/workersFocus.test.mjs index ebcb981..51d3b92 100644 --- a/tests/unit/workersFocus.test.mjs +++ b/tests/unit/workersFocus.test.mjs @@ -9,7 +9,7 @@ const { activeControl, focusLost, restoreFocus } = await loadModule('src/lib/wor function fakeDoc() { const body = { name: 'body' } const doc = { body, documentElement: { name: 'html' }, activeElement: body } - const el = (name, extra = {}) => ({ name, isConnected: true, disabled: false, focusCalls: 0, focus() { this.focusCalls += 1; doc.activeElement = this }, ...extra }) + const el = (name, extra = {}) => ({ name, isConnected: true, disabled: false, focusCalls: 0, focusArgs: [], focus(...args) { this.focusCalls += 1; this.focusArgs.push(args); doc.activeElement = this }, ...extra }) return { doc, body, el } } @@ -57,3 +57,12 @@ test('restoreFocus: nimmt den ersten Kandidaten, der noch da und frei ist; greif // Dinge ohne focus() (Attrappen, Textknoten) werden übersprungen assert.equal(restoreFocus(doc, [{ isConnected: true }, 'text', 7, second]), true); assert.equal(doc.activeElement, second) }) + +// Die Meldung oben (oder eine Zeile weit unten in einer langen Liste) darf den Fokus bekommen, ohne dass die Seite dorthin springt (Nachrunde R8) +test('restoreFocus: fokussiert mit preventScroll, damit die Seite nicht zur Meldung oder Zeile springt', () => { + const { doc, el } = fakeDoc() + const target = el('meldung') + assert.equal(restoreFocus(doc, [target]), true) + assert.equal(doc.activeElement, target) + assert.deepEqual(target.focusArgs, [[{ preventScroll: true }]]) // genau ein Aufruf, genau diese Option +})