Browse Source

无障碍:通过快捷键focus到特定类型区域的功能,允许一个类型有多个区域。

任一存 3 years ago
parent
commit
71e1fc27f3
3 changed files with 56 additions and 20 deletions
  1. 3 5
      web/README.md
  2. 50 3
      web/src/utils.js
  3. 3 12
      web/src/views/accessibility.vue

+ 3 - 5
web/README.md

@@ -28,6 +28,9 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
 * aria-theme-inverse: 手动添加。此节点的背景文字颜色会和无障碍菜单里的设置相反。
 * aria-no-zoom: 手动添加。此节点不会受无障碍菜单里缩放的控制。
 * aria-hide: 手动添加。此节点不会显示,只是为了tab键focus。
+* aria-navigation-area: 手动添加到导航区。
+* aria-viewport-area: 手动添加到视窗区。
+* aria-interactive-area: 手动添加到交互区。
 * aria-theme-[some color]: 自动添加。设置无障碍颜色时,这个class会被加到带有aria-control-target class的节点上。
 * aria-active: 自动添加。开启无障碍功能时添加到html和body上。
 * aria-magnifying: 自动添加。开启无障碍功能且开启其中的放大镜功能时添加到body上。
@@ -36,11 +39,6 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
 * `<style id="aria-big-cursor-style-node"></style>`: 大号光标样式代码。
 * `<style id="aria-zoom-style-node"></style>`: 缩放样式代码。
 
-## 特殊id
-导航区需设置id: navigation-area
-视窗区需设置id: viewport-area
-交互区需设置id: interactive-area
-
 ## 数据同步
 同一个域的多个页面的accessibility组件实例、该域下的唯一一份local storage之间的无障碍菜单设置会自动同步。
 

+ 50 - 3
web/src/utils.js

@@ -65,7 +65,53 @@ function isSameObject(object1, object2) {
   return true
 }
 
-function focusNextFocusableNode(treeWalker) {
+function getAndFocusNextNodeWithClassName(className) {
+  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.classList && [...nextNode.classList].some(item => item === className)) {
+      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.classList && [...nextNode.classList].some(item => item === className)) {
+        console.log('网上找到了')
+        targetNode = nextNode
+        break
+      }
+    }
+  }
+
+  if (targetNode) {
+    targetNode.focus()
+  }
+
+  return targetNode
+}
+
+function __focusNextFocusableNode(treeWalker) {
   // eslint-disable-next-line
   while(true) {
     const nextNode = treeWalker.nextNode()
@@ -89,7 +135,7 @@ function iterateOnFocusableNode(startNode, focusedNodeHandler) {
     // console.log('起始节点可以focus')
   } else {
     // console.log('起始节点不可以focus,focus到下一节点。')
-    const ret = focusNextFocusableNode(treeWalker)
+    const ret = __focusNextFocusableNode(treeWalker)
     if (!ret) {
       return
     }
@@ -97,7 +143,7 @@ function iterateOnFocusableNode(startNode, focusedNodeHandler) {
 
   const iterator = () => {
     focusedNodeHandler(treeWalker.currentNode).then(() => {
-      const result = focusNextFocusableNode(treeWalker)
+      const result = __focusNextFocusableNode(treeWalker)
       if (result) {
         // console.log('遍历到下一个节点!')
         iterator()
@@ -151,4 +197,5 @@ export default {
   isSameObject,
   iterateOnFocusableNode,
   debounce,
+  getAndFocusNextNodeWithClassName,
 }

+ 3 - 12
web/src/views/accessibility.vue

@@ -669,20 +669,11 @@ export default {
           this.onClickMagnifier()
         }
       } else if (e.key === "1" && e.altKey && !e.ctrlKey && !e.shiftKey) {
-        const navigationArea = document.getElementById('navigation-area')
-        if (navigationArea) {
-          navigationArea.focus()
-        }
+        utils.getAndFocusNextNodeWithClassName('aria-navigation-area')
       } else if (e.key === "2" && e.altKey && !e.ctrlKey && !e.shiftKey) {
-        const viewportArea = document.getElementById('viewport-area')
-        if (viewportArea) {
-          viewportArea.focus()
-        }
+        utils.getAndFocusNextNodeWithClassName('aria-viewport-area')
       } else if (e.key === "3" && e.altKey && !e.ctrlKey && !e.shiftKey) {
-        const interactiveArea = document.getElementById('interactive-area')
-        if (interactiveArea) {
-          interactiveArea.focus()
-        }
+        utils.getAndFocusNextNodeWithClassName('aria-interactive-area')
       }
     },
     loadStoredSettings() {