forked from nodejs/nodejs.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoutlineOnKeyboardNav.ts
More file actions
58 lines (49 loc) · 1.68 KB
/
outlineOnKeyboardNav.ts
File metadata and controls
58 lines (49 loc) · 1.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const TAB_KEYCODE = 9;
const FOCUS_ATTR = 'data-is-focused';
const BLUR_EVENT = 'blur';
const FOCUS_EVENT = 'focus';
const KEYDOWN_EVENT = 'keydown';
const MOUSEDOWN_EVENT = 'mousedown';
let IS_MOUSE_EVENT = false;
/**
* Attaches listeners for keydown, mousedown, focus, and blur to the document,
* which handle adding or removing focus outline css class for mouse events.
*/
export function addFocusOutlineListeners() {
const docEl = window.document.documentElement;
IS_MOUSE_EVENT = false;
docEl.addEventListener(KEYDOWN_EVENT, handleKeyDown, false);
docEl.addEventListener(MOUSEDOWN_EVENT, handleMouseDown, false);
docEl.addEventListener(FOCUS_EVENT, handleFocus, true);
docEl.addEventListener(BLUR_EVENT, handleBlur, true);
}
/**
* Detaches listeners
*/
export function removeFocusOutlineListeners() {
const docEl = window.document.documentElement;
if (docEl) {
docEl.removeEventListener(KEYDOWN_EVENT, handleKeyDown, false);
docEl.removeEventListener(MOUSEDOWN_EVENT, handleMouseDown, false);
docEl.removeEventListener(FOCUS_EVENT, handleFocus, true);
docEl.removeEventListener(BLUR_EVENT, handleBlur, true);
}
}
export function handleKeyDown(event: KeyboardEvent) {
if (event.keyCode === TAB_KEYCODE) {
IS_MOUSE_EVENT = false;
}
}
export function handleMouseDown(event: MouseEvent) {
IS_MOUSE_EVENT = true;
}
export function handleFocus(event: Event) {
if (IS_MOUSE_EVENT && event.target && event.target !== event.currentTarget) {
(event.target as Element).setAttribute(FOCUS_ATTR, 'true');
}
}
export function handleBlur(event: Event) {
if (event.target !== event.currentTarget) {
(event.target as Element).removeAttribute(FOCUS_ATTR);
}
}