Endprüfung Nachrunde R8: restoreFocus fokussiert mit preventScroll

Ohne die Option springt die Seite beim Zurückgeben des Fokus zum Ziel: bei einer Zeile weit unten in
einer langen Liste zur Meldung oben, und die Person verliert ihre Stelle. restoreFocus ruft jetzt
target.focus({ preventScroll: true }); der Fokus (und damit die Ansage) wandert, die Ansicht bleibt stehen.
Die Attrappe in workersFocus.test.mjs merkt sich die Argumente, ein neuer Test pinnt genau einen Aufruf
mit dieser Option.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-18 23:53:22 +00:00
1 parent 7c12cd22a6
commit c48d1834f4
2 files changed
+13 -2

No files matched your search

+3 -1
View File
@@ -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
}
+10 -1
View File
@@ -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
})