UNPKG

3.05 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4Object.defineProperty(exports, "__esModule", {
5 value: true
6});
7exports.backLastFocusNode = backLastFocusNode;
8exports.clearLastFocusNode = clearLastFocusNode;
9exports.getFocusNodeList = getFocusNodeList;
10exports.limitTabRange = limitTabRange;
11exports.saveLastFocusNode = saveLastFocusNode;
12var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
13var _isVisible = _interopRequireDefault(require("./isVisible"));
14function focusable(node) {
15 var includePositive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
16 if ((0, _isVisible.default)(node)) {
17 var nodeName = node.nodeName.toLowerCase();
18 var isFocusableElement =
19 // Focusable element
20 ['input', 'select', 'textarea', 'button'].includes(nodeName) ||
21 // Editable element
22 node.isContentEditable ||
23 // Anchor with href element
24 nodeName === 'a' && !!node.getAttribute('href');
25
26 // Get tabIndex
27 var tabIndexAttr = node.getAttribute('tabindex');
28 var tabIndexNum = Number(tabIndexAttr);
29
30 // Parse as number if validate
31 var tabIndex = null;
32 if (tabIndexAttr && !Number.isNaN(tabIndexNum)) {
33 tabIndex = tabIndexNum;
34 } else if (isFocusableElement && tabIndex === null) {
35 tabIndex = 0;
36 }
37
38 // Block focusable if disabled
39 if (isFocusableElement && node.disabled) {
40 tabIndex = null;
41 }
42 return tabIndex !== null && (tabIndex >= 0 || includePositive && tabIndex < 0);
43 }
44 return false;
45}
46function getFocusNodeList(node) {
47 var includePositive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
48 var res = (0, _toConsumableArray2.default)(node.querySelectorAll('*')).filter(function (child) {
49 return focusable(child, includePositive);
50 });
51 if (focusable(node, includePositive)) {
52 res.unshift(node);
53 }
54 return res;
55}
56var lastFocusElement = null;
57
58/** @deprecated Do not use since this may failed when used in async */
59function saveLastFocusNode() {
60 lastFocusElement = document.activeElement;
61}
62
63/** @deprecated Do not use since this may failed when used in async */
64function clearLastFocusNode() {
65 lastFocusElement = null;
66}
67
68/** @deprecated Do not use since this may failed when used in async */
69function backLastFocusNode() {
70 if (lastFocusElement) {
71 try {
72 // 元素可能已经被移动了
73 lastFocusElement.focus();
74
75 /* eslint-disable no-empty */
76 } catch (e) {
77 // empty
78 }
79 /* eslint-enable no-empty */
80 }
81}
82function limitTabRange(node, e) {
83 if (e.keyCode === 9) {
84 var tabNodeList = getFocusNodeList(node);
85 var lastTabNode = tabNodeList[e.shiftKey ? 0 : tabNodeList.length - 1];
86 var leavingTab = lastTabNode === document.activeElement || node === document.activeElement;
87 if (leavingTab) {
88 var target = tabNodeList[e.shiftKey ? tabNodeList.length - 1 : 0];
89 target.focus();
90 e.preventDefault();
91 }
92 }
93}
\No newline at end of file