适用于谷歌和 Edge 浏览器的快捷键解决方案

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
(function () {
  'use strict';

  function isVisible(t) {
    return !! (!t.hasAttribute('disabled') && t.getAttribute('aria-hidden') !== 'true' && t.offsetParent !== null);
  }

  function removeAccesskeyAttribute(selector) {
    document.querySelectorAll(selector).forEach(function(el) {
      el.removeAttribute('accesskey');
    });
  }
  function addClass(selector, clsName) {
    document.querySelectorAll(selector).forEach(function(el) {
      el.classList.add(clsName);
    });
  }

  function gi(i, len, op) {
    let n = op == '+' ? +1 : -1;
    i = i + n;
    if (i >= len) {
      i = 0;
    }
    if (i < 0) {
      i = len - 1;
    }
    return i;
  }

  function _toFocus(el) {
    let tagName = el.tagName.toLowerCase();
    let tagNames = ['div', 'p', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'form', 'img', 'nav', 'header', 'main', 'footer', 'section', 'aside'];
    if (tagNames.includes(tagName) || (tagName == 'a' && !el.hasAttribute('href'))) {
      if (!el.hasAttribute('tabindex')) {
        el.setAttribute('tabindex', '-1');
      }
    }
    el.focus();
  }

  function toFocus(focusSelector, op) {
    let els = [...document.body.querySelectorAll('*')];
    let len = els.length;
    let aeIndex = Math.max(0, els.indexOf(document.activeElement));
    let i = aeIndex == 0 ? 0 : gi(aeIndex, len, op);
    do {
      if (els[i].matches(focusSelector) && isVisible(els[i])) {
        _toFocus(els[i]);
        break;
      }
      i = gi(i, len, op);
    } while ( i != aeIndex );
  }

  function nextFocus(selector) {
    toFocus(selector, '+');
  }

  function previousFocus(selector) {
    toFocus(selector, '-');
  }

  function isIE() {
    return ( !! window.ActiveXObject || "ActiveXObject" in window);
  }

  if (!isIE()) {
    let keys = [];
    document.querySelectorAll('[accesskey]').forEach(function(el) {
      let key = el.getAttribute('accesskey');
      if (!keys.includes(key)) {
        keys.push(key);
      }
    });
    keys.forEach(function(key) {
      addClass('[accesskey="' + key + '"]', 'accesskey-' + key);
      removeAccesskeyAttribute('[accesskey="' + key + '"]');
    });

    document.addEventListener('keydown',
    function(e) {
      keys.forEach(function(key) {
        let keyCode = key.toUpperCase().charCodeAt();
        if (e.altKey && e.shiftKey && e.keyCode == keyCode) {
          e.preventDefault();
          previousFocus('.accesskey-' + key);
        } else if (e.altKey && e.keyCode == keyCode) {
          e.preventDefault();
          nextFocus('.accesskey-' + key);
        }
      });
    },
    null);
  }

}());
updatedupdated2020-10-072020-10-07