mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-01 22:10:27 +00:00
125 lines
3.0 KiB
JavaScript
125 lines
3.0 KiB
JavaScript
import KEYCODE from './keycode';
|
|
import { each } from './object';
|
|
|
|
/**
|
|
* 用于切换页面元素的焦点
|
|
*/
|
|
|
|
/**
|
|
* 元素是否可见
|
|
* @private
|
|
* @param {Element} node
|
|
* @return {Boolean}
|
|
*/
|
|
function _isVisible(node) {
|
|
while (node) {
|
|
if (node === document.body || node === document.documentElement) {
|
|
break;
|
|
}
|
|
if (node.style.display === 'none' || node.style.visibility === 'hidden') {
|
|
return false;
|
|
}
|
|
node = node.parentNode;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 元素是否可以获取焦点
|
|
* @private
|
|
* @param {Element} node
|
|
* @return {Boolean}
|
|
*/
|
|
function _isFocusable(node) {
|
|
var nodeName = node.nodeName.toLowerCase();
|
|
var tabIndex = parseInt(node.getAttribute('tabindex'), 10);
|
|
var hasTabIndex = !isNaN(tabIndex) && tabIndex > -1;
|
|
|
|
if (_isVisible(node)) {
|
|
if (nodeName === 'input') {
|
|
return !node.disabled && node.type !== 'hidden';
|
|
} else if (['select', 'textarea', 'button'].indexOf(nodeName) > -1) {
|
|
return !node.disabled;
|
|
} else if (nodeName === 'a') {
|
|
return node.getAttribute('href') || hasTabIndex;
|
|
} else {
|
|
return hasTabIndex;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 列出能获取焦点的子节点
|
|
* @param {Element} node 容器节点
|
|
* @return {Array<Element>}
|
|
*/
|
|
export function getFocusNodeList(node) {
|
|
var res = [];
|
|
var nodeList = node.querySelectorAll('*');
|
|
|
|
each(nodeList, function (item) {
|
|
if (_isFocusable(item)) {
|
|
var method = item.getAttribute('data-auto-focus') ? 'unshift' : 'push';
|
|
res[method](item);
|
|
}
|
|
});
|
|
|
|
if (_isFocusable(node)) {
|
|
res.unshift(node);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// 用于记录上一次获得焦点的无素
|
|
var lastFocusElement = null;
|
|
|
|
/**
|
|
* 保存最近一次获得焦点的无素
|
|
*/
|
|
export function saveLastFocusNode() {
|
|
lastFocusElement = document.activeElement;
|
|
}
|
|
|
|
/**
|
|
* 清除焦点记录
|
|
*/
|
|
export function clearLastFocusNode() {
|
|
lastFocusElement = null;
|
|
}
|
|
|
|
/**
|
|
* 尝试将焦点切换到上一个元素
|
|
*/
|
|
export function backLastFocusNode() {
|
|
if (lastFocusElement) {
|
|
try {
|
|
// 元素可能已经被移动了
|
|
lastFocusElement.focus();
|
|
} catch (e) {
|
|
// ignore ...
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 在限制的范围内切换焦点
|
|
* @param {Element} node 容器节点
|
|
* @param {Event} e 键盘事件
|
|
*/
|
|
export function limitTabRange(node, e) {
|
|
if (e.keyCode === KEYCODE.TAB) {
|
|
var tabNodeList = getFocusNodeList(node);
|
|
var maxIndex = tabNodeList.length - 1;
|
|
var index = tabNodeList.indexOf(document.activeElement);
|
|
|
|
if (index > -1) {
|
|
var targetIndex = index + (e.shiftKey ? -1 : 1);
|
|
targetIndex < 0 && (targetIndex = maxIndex);
|
|
targetIndex > maxIndex && (targetIndex = 0);
|
|
tabNodeList[targetIndex].focus();
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
} |