123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- function mapTags(tag) {
- let ret = ''
- switch (tag) {
- case 'A':
- ret = 'Link'
- break
- case 'BUTTON':
- ret = 'Button'
- 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]
- // 如果天然能focus,但没有被加上tabindex属性,比如focus到了第三方组件内部的可focus元素,直接返回。
- if (
- ['A', 'AREA', 'BUTTON', 'INPUT', 'SELECT', 'IFRAME'].includes(meaningfulNode.tagName) &&
- !meaningfulNode.getAttribute('tabindex')
- ) {
- return
- }
-
- while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) {
- meaningfulNode = meaningfulNode.parentNode
- if (!meaningfulNode) {
- return
- }
- }
-
- // mouseover事件冒泡到有data-aria-xxx-area attribute的区域时,不应该提取该区域的无障碍辅助信息。
- if (e.type === 'mouseover' && (
- meaningfulNode.getAttribute('data-aria-navigation-area') !== null ||
- meaningfulNode.getAttribute('data-aria-viewport-area') !== null ||
- meaningfulNode.getAttribute('data-aria-interaction-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,
- }
|