UNPKG

3.49 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4exports.getFocusNodeList = getFocusNodeList;
5exports.saveLastFocusNode = saveLastFocusNode;
6exports.clearLastFocusNode = clearLastFocusNode;
7exports.backLastFocusNode = backLastFocusNode;
8exports.limitTabRange = limitTabRange;
9
10var _keycode = require('./keycode');
11
12var _keycode2 = _interopRequireDefault(_keycode);
13
14var _object = require('./object');
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18/**
19 * 用于切换页面元素的焦点
20 */
21
22/**
23 * 元素是否可见
24 * @private
25 * @param {Element} node
26 * @return {Boolean}
27 */
28function _isVisible(node) {
29 while (node) {
30 var _node = node,
31 nodeName = _node.nodeName;
32
33 if (nodeName === 'BODY' || nodeName === 'HTML') {
34 break;
35 }
36 if (node.style.display === 'none' || node.style.visibility === 'hidden') {
37 return false;
38 }
39 node = node.parentNode;
40 }
41 return true;
42}
43
44/**
45 * 元素是否可以获取焦点
46 * @private
47 * @param {Element} node
48 * @return {Boolean}
49 */
50function _isFocusable(node) {
51 var nodeName = node.nodeName.toLowerCase();
52 var tabIndex = parseInt(node.getAttribute('tabindex'), 10);
53 var hasTabIndex = !isNaN(tabIndex) && tabIndex > -1;
54
55 if (_isVisible(node)) {
56 if (nodeName === 'input') {
57 return !node.disabled && node.type !== 'hidden';
58 } else if (['select', 'textarea', 'button'].indexOf(nodeName) > -1) {
59 return !node.disabled;
60 } else if (nodeName === 'a') {
61 return node.getAttribute('href') || hasTabIndex;
62 } else {
63 return hasTabIndex;
64 }
65 }
66 return false;
67}
68
69/**
70 * 列出能获取焦点的子节点
71 * @param {Element} node 容器节点
72 * @return {Array<Element>}
73 */
74function getFocusNodeList(node) {
75 var res = [];
76 var nodeList = node.querySelectorAll('*');
77
78 (0, _object.each)(nodeList, function (item) {
79 if (_isFocusable(item)) {
80 var method = item.getAttribute('data-auto-focus') ? 'unshift' : 'push';
81 res[method](item);
82 }
83 });
84
85 if (_isFocusable(node)) {
86 res.unshift(node);
87 }
88
89 return res;
90}
91
92// 用于记录上一次获得焦点的无素
93var lastFocusElement = null;
94
95/**
96 * 保存最近一次获得焦点的无素
97 */
98function saveLastFocusNode() {
99 lastFocusElement = document.activeElement;
100}
101
102/**
103 * 清除焦点记录
104 */
105function clearLastFocusNode() {
106 lastFocusElement = null;
107}
108
109/**
110 * 尝试将焦点切换到上一个元素
111 */
112function backLastFocusNode() {
113 if (lastFocusElement) {
114 try {
115 // 元素可能已经被移动了
116 lastFocusElement.focus();
117 } catch (e) {
118 // ignore ...
119 }
120 }
121}
122
123/**
124 * 在限制的范围内切换焦点
125 * @param {Element} node 容器节点
126 * @param {Event} e 键盘事件
127 */
128function limitTabRange(node, e) {
129 if (e.keyCode === _keycode2.default.TAB) {
130 var tabNodeList = getFocusNodeList(node);
131 var maxIndex = tabNodeList.length - 1;
132 var index = tabNodeList.indexOf(document.activeElement);
133
134 if (index > -1) {
135 var targetIndex = index + (e.shiftKey ? -1 : 1);
136 targetIndex < 0 && (targetIndex = maxIndex);
137 targetIndex > maxIndex && (targetIndex = 0);
138 tabNodeList[targetIndex].focus();
139 e.preventDefault();
140 }
141 }
142}
\No newline at end of file