Skip to content

Commit 37ee469

Browse files
committed
Subscribe to events
Consolidates adding and removing listeners into a subscription pattern.
1 parent 791adef commit 37ee469

File tree

1 file changed

+31
-31
lines changed

1 file changed

+31
-31
lines changed

index.js

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,48 +37,47 @@ class DetailsMenuElement extends HTMLElement {
3737
if (!summary.hasAttribute('role')) summary.setAttribute('role', 'button')
3838
}
3939

40-
const subscriptions = [focusOnOpen(details)]
41-
const state = {
42-
details,
43-
subscriptions,
44-
loaded: false,
45-
shouldCommit: shouldCommit.bind(null, details, this),
46-
keydown: keydown.bind(null, details, this),
47-
loadFragment: loadFragment.bind(null, details, this),
48-
closeCurrentMenu: closeCurrentMenu.bind(null, details)
49-
}
50-
states.set(this, state)
51-
52-
details.addEventListener('click', state.shouldCommit)
53-
details.addEventListener('change', state.shouldCommit)
54-
details.addEventListener('keydown', state.keydown)
55-
details.addEventListener('toggle', state.loadFragment, {once: true})
56-
details.addEventListener('toggle', state.closeCurrentMenu)
57-
if (this.preload) {
58-
details.addEventListener('mouseover', state.loadFragment, {once: true})
59-
}
40+
const subscriptions = [
41+
fromEvent(details, 'click', e => shouldCommit(details, this, e)),
42+
fromEvent(details, 'change', e => shouldCommit(details, this, e)),
43+
fromEvent(details, 'keydown', e => keydown(details, this, e)),
44+
fromEvent(details, 'toggle', () => loadFragment(details, this), {once: true}),
45+
fromEvent(details, 'toggle', () => closeCurrentMenu(details)),
46+
this.preload
47+
? fromEvent(details, 'mouseover', () => loadFragment(details, this), {once: true})
48+
: NullSubscription,
49+
focusOnOpen(details)
50+
]
51+
52+
states.set(this, {subscriptions, loaded: false})
6053
}
6154

6255
disconnectedCallback() {
6356
const state = states.get(this)
6457
if (!state) return
65-
6658
states.delete(this)
67-
68-
const {details, subscriptions} = state
69-
for (const sub of subscriptions) {
59+
for (const sub of state.subscriptions) {
7060
sub.unsubscribe()
7161
}
72-
details.removeEventListener('click', state.shouldCommit)
73-
details.removeEventListener('change', state.shouldCommit)
74-
details.removeEventListener('keydown', state.keydown)
75-
details.removeEventListener('toggle', state.loadFragment, {once: true})
76-
details.removeEventListener('toggle', state.closeCurrentMenu)
77-
details.removeEventListener('mouseover', state.loadFragment, {once: true})
7862
}
7963
}
8064

8165
const states = new WeakMap()
66+
const NullSubscription = {unsubscribe() {}}
67+
68+
function fromEvent(
69+
target: EventTarget,
70+
eventName: string,
71+
onNext: EventHandler,
72+
options: EventListenerOptionsOrUseCapture = false
73+
) {
74+
target.addEventListener(eventName, onNext, options)
75+
return {
76+
unsubscribe: () => {
77+
target.removeEventListener(eventName, onNext, options)
78+
}
79+
}
80+
}
8281

8382
function loadFragment(details: Element, menu: DetailsMenuElement) {
8483
const src = menu.getAttribute('src')
@@ -217,7 +216,8 @@ function commit(selected: Element, details: Element) {
217216
)
218217
}
219218

220-
function keydown(details: Element, menu: DetailsMenuElement, event: KeyboardEvent) {
219+
function keydown(details: Element, menu: DetailsMenuElement, event: Event) {
220+
if (!(event instanceof KeyboardEvent)) return
221221
const isSummaryFocused = event.target instanceof Element && event.target.tagName === 'SUMMARY'
222222

223223
// Ignore key presses from nested details.

0 commit comments

Comments
 (0)