function mapTags(tag) { let ret = '' switch (tag) { case 'A': ret = 'Link: ' break case 'BUTTON': ret = 'Link: ' break case 'IMG': ret = 'Image: ' break case 'INPUT': ret = 'Textbox: ' break case 'TEXTAREA': ret = 'Textbox: ' break default: ret = 'Text: ' break } return ret } function extractTextForMagnify(e) { let meaningfulNode = e.path[0] console.log(meaningfulNode); while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) { meaningfulNode = meaningfulNode.parentNode if (!meaningfulNode) { return } } if (e.type === 'mouseover' && ( meaningfulNode.getAttribute('data-aria-navigation-area') !== null || meaningfulNode.getAttribute('data-aria-viewport-area') !== null || meaningfulNode.getAttribute('data-aria-interactive-area') !== null ) ) { return } let elemType = '' const ariaLabel = meaningfulNode.getAttribute('aria-label') if (ariaLabel !== null) { elemType = ariaLabel } else { elemType = mapTags(meaningfulNode.tagName) } let elemDisc = '' const ariaDescription = meaningfulNode.getAttribute('aria-description') if (ariaDescription !== null) { elemDisc = ariaDescription } else { elemDisc = meaningfulNode.innerText } return { elemType, elemDisc } } function isObject(p) { return Object.prototype.toString.call(p) === '[object Object]' } // 判断两个对象内容是否相同 function isSameObject(object1, object2) { const keys1 = Object.keys(object1) const keys2 = Object.keys(object2) if (keys1.length !== keys2.length) { return false } for (let index = 0; index < keys1.length; index++) { const val1 = object1[keys1[index]] const val2 = object2[keys2[index]] const areObjects = isObject(val1) && isObject(val2) if ( (areObjects && !isSameObject(val1, val2)) || (!areObjects && (val1 !== val2)) ) { return false } } return true } function getAndFocusNextNodeWithCustomAttribute(attriName) { const startNode = (document.activeElement || document.body) const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT) treeWalker.currentNode = startNode let targetNode = null // eslint-disable-next-line while(true) { const nextNode = treeWalker.nextNode() if (!nextNode) { console.log('往下没找到') break } if (nextNode.dataset[attriName] !== undefined) { console.log('往下找到了') targetNode = nextNode break } } if (!targetNode && (startNode !== document.body)) { treeWalker.currentNode = document.body // eslint-disable-next-line while(true) { const nextNode = treeWalker.nextNode() if (!nextNode) { console.log('往上也没找到') break } if (nextNode.dataset[attriName] !== undefined) { console.log('往上找到了') targetNode = nextNode break } } } if (targetNode) { targetNode.focus() if (document.activeElement !== targetNode) { targetNode.setAttribute('tabindex', '0') targetNode.focus() } } return targetNode } function __focusNextFocusableNode(treeWalker) { // eslint-disable-next-line while(true) { const nextNode = treeWalker.nextNode() if (!nextNode) { return false } if (nextNode.focus) { nextNode.focus() if (document.activeElement === nextNode) { return true } } } } function iterateOnFocusableNode(startNode, focusedNodeHandler) { const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT) treeWalker.currentNode = startNode treeWalker.currentNode.focus() if (document.activeElement === treeWalker.currentNode) { // console.log('起始节点可以focus') } else { // console.log('起始节点不可以focus,focus到下一节点。') const ret = __focusNextFocusableNode(treeWalker) if (!ret) { return } } const iterator = () => { focusedNodeHandler(treeWalker.currentNode).then(() => { const result = __focusNextFocusableNode(treeWalker) if (result) { // console.log('遍历到下一个节点!') iterator() } else { // console.log('遍历结束!') } }).catch((e) => { // console.log('遍历中止!', e) }) } iterator() } /** * 返回一个自带消抖效果的函数,用res表示。 * * fn: 需要被消抖的函数 * delay: 消抖时长 * isImmediateCall: 是在第一次调用时立即执行fn,还是在最后一次调用后等delay时长再调用fn */ function debounce(fn, delay, isImmediateCall = false) { let timer = null // 上次调用的时刻 let lastCallTime = 0 if (isImmediateCall) { return function (...args) { const context = this const currentTime = Date.now() if (currentTime - lastCallTime >= delay) { fn.apply(context, args) } lastCallTime = currentTime } } else { return function (...args) { if (timer) { clearTimeout(timer) } const context = this timer = setTimeout(() => { fn.apply(context, args) }, delay) } } } export default { mapTags, extractTextForMagnify, isSameObject, iterateOnFocusableNode, debounce, getAndFocusNextNodeWithCustomAttribute, }