-
Notifications
You must be signed in to change notification settings - Fork 811
/
Copy pathscopeTab.js
87 lines (70 loc) · 2.09 KB
/
scopeTab.js
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import findTabbable from "./tabbable";
function getActiveElement(el = document) {
return el.activeElement.shadowRoot
? getActiveElement(el.activeElement.shadowRoot)
: el.activeElement;
}
export default function scopeTab(node, event) {
const tabbable = findTabbable(node);
if (!tabbable.length) {
// Do nothing, since there are no elements that can receive focus.
event.preventDefault();
return;
}
let target;
const shiftKey = event.shiftKey;
const head = tabbable[0];
const tail = tabbable[tabbable.length - 1];
const activeElement = getActiveElement();
// proceed with default browser behavior on tab.
// Focus on last element on shift + tab.
if (node === activeElement) {
if (!shiftKey) return;
target = tail;
}
if (tail === activeElement && !shiftKey) {
target = head;
}
if (head === activeElement && shiftKey) {
target = tail;
}
if (target) {
event.preventDefault();
target.focus();
return;
}
// Safari radio issue.
//
// Safari does not move the focus to the radio button,
// so we need to force it to really walk through all elements.
//
// This is very error prone, since we are trying to guess
// if it is a safari browser from the first occurence between
// chrome or safari.
//
// The chrome user agent contains the first ocurrence
// as the 'chrome/version' and later the 'safari/version'.
const checkSafari = /(\bChrome\b|\bSafari\b)\//.exec(navigator.userAgent);
const isSafariDesktop =
checkSafari != null &&
checkSafari[1] != "Chrome" &&
/\biPod\b|\biPad\b/g.exec(navigator.userAgent) == null;
// If we are not in safari desktop, let the browser control
// the focus
if (!isSafariDesktop) return;
var x = tabbable.indexOf(activeElement);
if (x > -1) {
x += shiftKey ? -1 : 1;
}
target = tabbable[x];
// If the tabbable element does not exist,
// focus head/tail based on shiftKey
if (typeof target === "undefined") {
event.preventDefault();
target = shiftKey ? tail : head;
target.focus();
return;
}
event.preventDefault();
target.focus();
}