|
@@ -24,59 +24,87 @@ function mapTags(tag) {
|
|
|
return ret
|
|
|
}
|
|
|
|
|
|
-let lastMeaningfulNode = null
|
|
|
-function extractTextForMagnify(e, allowRepeatd = false) {
|
|
|
+function extractTextForFocus(e) {
|
|
|
let meaningfulNode = e.target
|
|
|
|
|
|
- if (e.type === 'mouseover') {
|
|
|
- while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) {
|
|
|
- meaningfulNode = meaningfulNode.parentNode
|
|
|
- if (!meaningfulNode) {
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
+ // 如果天然能focus,但没有被加上tabindex属性,比如focus到了第三方组件内部的可focus元素,直接返回。
|
|
|
+ if (
|
|
|
+ ['A', 'AREA', 'BUTTON', 'INPUT', 'SELECT', 'IFRAME'].includes(meaningfulNode.tagName) &&
|
|
|
+ !meaningfulNode.getAttribute('tabindex')
|
|
|
+ ) {
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- if (meaningfulNode.getAttribute('tabindex') === '-1') {
|
|
|
+ while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) {
|
|
|
+ meaningfulNode = meaningfulNode.parentNode
|
|
|
+ if (!meaningfulNode) {
|
|
|
return
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // mouseover事件冒泡到有data-aria-xxx-area attribute的区域包裹元素时,不应该提取该区域包裹元素的无障碍辅助信息。
|
|
|
- if (
|
|
|
- meaningfulNode.getAttribute('data-aria-navigation-area') !== null ||
|
|
|
- meaningfulNode.getAttribute('data-aria-viewport-area') !== null ||
|
|
|
- meaningfulNode.getAttribute('data-aria-interaction-area') !== null
|
|
|
- ) {
|
|
|
- return
|
|
|
- }
|
|
|
- } else if (e.type === 'focusin') {
|
|
|
- // 如果天然能focus,但没有被加上tabindex属性,比如focus到了第三方组件内部的可focus元素,直接返回。
|
|
|
- if (
|
|
|
- ['A', 'AREA', 'BUTTON', 'INPUT', 'SELECT', 'IFRAME'].includes(meaningfulNode.tagName) &&
|
|
|
- !meaningfulNode.getAttribute('tabindex')
|
|
|
- ) {
|
|
|
- return
|
|
|
- }
|
|
|
+ // 约定:tabindex属性值为-1的元素只用于在点击有data-aria-xxx-area attribute的区域包裹元素的子孙元素时,避免focus到区域包裹元素。
|
|
|
+ if (meaningfulNode.getAttribute('tabindex') === '-1') {
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) {
|
|
|
- meaningfulNode = meaningfulNode.parentNode
|
|
|
- if (!meaningfulNode) {
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
+ let elemType = ''
|
|
|
+ const ariaLabel = meaningfulNode.getAttribute('aria-label')
|
|
|
+ if (ariaLabel !== null) {
|
|
|
+ elemType = ariaLabel
|
|
|
+ } else {
|
|
|
+ elemType = mapTags(meaningfulNode.tagName)
|
|
|
+ }
|
|
|
|
|
|
- // 约定:tabindex属性值为-1的元素只用于在点击有data-aria-xxx-area attribute的区域包裹元素的子孙元素时,避免focus到区域包裹元素。
|
|
|
- if (meaningfulNode.getAttribute('tabindex') === '-1') {
|
|
|
- return
|
|
|
- }
|
|
|
+ let elemDisc = ''
|
|
|
+ const ariaDescription = meaningfulNode.getAttribute('aria-description')
|
|
|
+ if (ariaDescription !== null) {
|
|
|
+ elemDisc = ariaDescription
|
|
|
+ } else {
|
|
|
+ elemDisc = meaningfulNode.innerText
|
|
|
}
|
|
|
|
|
|
- if (!allowRepeatd) {
|
|
|
- if (meaningfulNode === lastMeaningfulNode) {
|
|
|
+ return {
|
|
|
+ elemType,
|
|
|
+ elemDisc,
|
|
|
+ ariaNode: meaningfulNode,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+let lastMeaningfulNode = null
|
|
|
+function extractTextForMouseOver(e) {
|
|
|
+ let meaningfulNode = e.target
|
|
|
+
|
|
|
+ while (!meaningfulNode.getAttribute || !meaningfulNode.getAttribute('tabindex')) {
|
|
|
+ meaningfulNode = meaningfulNode.parentNode
|
|
|
+ if (!meaningfulNode) {
|
|
|
return
|
|
|
}
|
|
|
- lastMeaningfulNode = meaningfulNode
|
|
|
+ }
|
|
|
+
|
|
|
+ if (meaningfulNode.getAttribute('tabindex') === '-1') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // mouseover事件冒泡到有data-aria-xxx-area attribute的区域包裹元素时,不应该提取该区域包裹元素的无障碍辅助信息。
|
|
|
+ if (
|
|
|
+ meaningfulNode.getAttribute('data-aria-navigation-area') !== null ||
|
|
|
+ meaningfulNode.getAttribute('data-aria-viewport-area') !== null ||
|
|
|
+ meaningfulNode.getAttribute('data-aria-interaction-area') !== null
|
|
|
+ ) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果只是在需要朗读的子元素之间进进出出,第一次需要朗读,以后就不需要朗读了。
|
|
|
+ let relatedMeaningfulNode = e.relatedTarget
|
|
|
+ while (relatedMeaningfulNode && (!relatedMeaningfulNode.getAttribute || !relatedMeaningfulNode.getAttribute('tabindex'))) {
|
|
|
+ relatedMeaningfulNode = relatedMeaningfulNode.parentNode
|
|
|
+ }
|
|
|
+ if (relatedMeaningfulNode === meaningfulNode && lastMeaningfulNode === meaningfulNode) {
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
+ lastMeaningfulNode = meaningfulNode
|
|
|
+
|
|
|
let elemType = ''
|
|
|
const ariaLabel = meaningfulNode.getAttribute('aria-label')
|
|
|
if (ariaLabel !== null) {
|
|
@@ -332,7 +360,8 @@ class DebounceScheduler {
|
|
|
|
|
|
export default {
|
|
|
mapTags,
|
|
|
- extractTextForMagnify,
|
|
|
+ extractTextForFocus,
|
|
|
+ extractTextForMouseOver,
|
|
|
isSameObject,
|
|
|
getAndFocusNextNodeWithCustomAttribute,
|
|
|
iterateOnFocusableNode,
|