Skip to content

Commit fc01316

Browse files
committed
feat: use delegated event listener for keyboard focus
This allows for non-MarkdownButtonElement members to also handle focus management keyboard shortcuts, as the event binding is per-toolbar not per-button
1 parent 72c0c73 commit fc01316

File tree

1 file changed

+35
-24
lines changed

1 file changed

+35
-24
lines changed

index.js

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,10 @@
22

33
function keydown(fn: KeyboardEventHandler): KeyboardEventHandler {
44
return function(event: KeyboardEvent) {
5-
const key = event.key
6-
if (key === ' ' || key === 'Enter') {
5+
if (event.key === ' ' || event.key === 'Enter') {
76
event.preventDefault()
87
fn(event)
98
}
10-
if (key === 'ArrowRight' || key === 'ArrowLeft' || key === 'Home' || key === 'End') {
11-
const target = event.currentTarget
12-
if (!(target instanceof HTMLElement)) return
13-
if (!target.hasAttribute('data-md-button')) return
14-
const toolbar = target.closest('markdown-toolbar')
15-
if (!(toolbar instanceof MarkdownToolbarElement)) return
16-
17-
const buttons = []
18-
for (const button of toolbar.querySelectorAll('[data-md-button]')) {
19-
button.setAttribute('tabindex', '-1')
20-
buttons.push(button)
21-
}
22-
let i = 0
23-
if (key === 'ArrowLeft') i = buttons.indexOf(target) - 1
24-
if (key === 'ArrowRight') i = buttons.indexOf(target) + 1
25-
if (key === 'End') i = buttons.length - 1
26-
if (i < 0) i = buttons.length - 1
27-
if (i > buttons.length - 1) i = 0
28-
29-
buttons[i].setAttribute('tabindex', '0')
30-
buttons[i].focus()
31-
}
329
}
3310
}
3411

@@ -248,6 +225,9 @@ class MarkdownToolbarElement extends HTMLElement {
248225
if (!this.hasAttribute('role')) {
249226
this.setAttribute('role', 'toolbar')
250227
}
228+
const focusKeydownfn = focusKeydown.bind(null, this)
229+
this.addEventListener('keydown', focusKeydownfn)
230+
focusListeners.set(this, focusKeydownfn)
251231
const fn = shortcut.bind(null, this)
252232
if (this.field) {
253233
this.field.addEventListener('keydown', fn)
@@ -263,6 +243,10 @@ class MarkdownToolbarElement extends HTMLElement {
263243
this.field.removeEventListener('keydown', fn)
264244
shortcutListeners.delete(this)
265245
}
246+
const focusKeydownfn = focusListeners.get(this)
247+
if (focusKeydownfn) {
248+
this.removeEventListener('keydown', focusKeydownfn)
249+
}
266250
}
267251

268252
get field(): ?HTMLTextAreaElement {
@@ -273,6 +257,33 @@ class MarkdownToolbarElement extends HTMLElement {
273257
}
274258
}
275259

260+
const focusListeners = new WeakMap()
261+
262+
function focusKeydown(toolbar: MarkdownToolbarElement, event: KeyboardEvent) {
263+
const key = event.key
264+
if (key !== 'ArrowRight' && key !== 'ArrowLeft' && key !== 'Home' && key !== 'End') return
265+
const target = event.target
266+
if (!(target instanceof HTMLElement)) return
267+
if (!target.hasAttribute('data-md-button')) return
268+
if (target.closest('markdown-toolbar') !== toolbar) return
269+
270+
const buttons = []
271+
for (const button of toolbar.querySelectorAll('[data-md-button]')) {
272+
if (!(button instanceof MarkdownButtonElement)) continue
273+
button.setAttribute('tabindex', '-1')
274+
buttons.push(button)
275+
}
276+
let i = 0
277+
if (key === 'ArrowLeft') i = buttons.indexOf(target) - 1
278+
if (key === 'ArrowRight') i = buttons.indexOf(target) + 1
279+
if (key === 'End') i = buttons.length - 1
280+
if (i < 0) i = buttons.length - 1
281+
if (i > buttons.length - 1) i = 0
282+
283+
buttons[i].setAttribute('tabindex', '0')
284+
buttons[i].focus()
285+
}
286+
276287
const shortcutListeners = new WeakMap()
277288

278289
function shortcut(toolbar: Element, event: KeyboardEvent) {

0 commit comments

Comments
 (0)