3

这应该很简单,但由于某种原因它不起作用,我在正确的时间得到了正确的 console.logs,但焦点没有转到正确的地方,请参考我的 jsfiddle

https://jsfiddle.net/bqt0np9d/

function checkTabPress(e) {
    "use strict";
    // pick passed event of global event object
    e = e || event;

    if (e.keyCode === 9) {
        if (e.shiftKey) {
            console.log('back tab pressed');
            firstItem.onblur=function(){
                console.log('last a focus left');
                lastItem.focus();
            };
            e.preventDefault();
        }
        console.log('tab pressed');
        lastItem.onblur=function(){
            console.log('last a focus left');
            firstItem.focus();
        };
        e.preventDefault();
    }
}
modal.addEventListener('keyup', checkTabPress);
4

4 回答 4

1

我必须将焦点锁定在我们在 React 组件中使用过的模式中。我为 KEY DOWN 添加了 eventListner 并收集了 Tab 和 Shift+Tab

class Modal extends Component {
    componentDidMount() {
        window.addEventListener("keyup", this.handleKeyUp, false);
        window.addEventListener("keydown", this.handleKeyDown, false);
    }

    componentWillUnmount() {
        window.removeEventListener("keyup", this.handleKeyUp, false);
        window.removeEventListener("keydown", this.handleKeyDown, false);
    }

    handleKeyDown = (e) => {

        //Fetch node list from which required elements could be grabbed as needed.
        const modal = document.getElementById("modal_parent");
        const tags = [...modal.querySelectorAll('select, input, textarea, button, a, li')].filter(e1 => window.getComputedStyle(e1).getPropertyValue('display') === 'block');
        const focusable = modal.querySelectorAll('button, [href], input, select, textarea, li, a,[tabindex]:not([tabindex="-1"])');
        const firstFocusable = focusable[0];
        const lastFocusable = focusable[focusable.length - 1];

        if (e.ctrlKey || e.altKey) {
            return;
        }

        const keys = {
            9: () => { //9 = TAB
                if (e.shiftKey && e.target === firstFocusable) {
                    lastFocusable.focus();
                }

                if (e.target === lastFocusable) {
                    firstFocusable.focus();
                }
            }
        };

        if (keys[e.keyCode]) {
            keys[e.keyCode]();
        }
    }
}
于 2019-11-05T00:01:30.997 回答
0

对事件e.preventDefault()没有影响keyup(因为默认浏览器操作已经被触发)

尽管如此,您的示例仍然有效。但前提是模态之前和之后有链接

如果您使用以下内容更改您的 HTML 代码,在模态框之前添加一个链接,在模态框之后添加一个链接;您会看到您的注意力被困在模态中:

 <a href="#">other link</a>
 <div id="modal">
     <a href="#">Link One</a>
     <a href="#">Link Two</a>
 </div>
 <a href="#">other link</a>

那是因为在这种情况下没有默认的浏览器操作,然后没有阻止的操作。

于 2015-10-08T09:37:38.337 回答
0

在模态中捕获焦点很难靠自己完成。如果您能够在项目中安装第三方依赖项,则可以使用focus-trap包。

您可以使用 vanilla Javascript 轻松地将焦点集中到任何组件上;

import { createFocusTrap } from 'focus-trap'

const modal = document.getElementById('modal')

const focusTrap = createFocusTrap('#modal', {
    onActivate: function () {
        modal.className = 'trap is-visible'
    },
    onDeactivate: function () {
        modal.className = 'trap'
    },
})

document.getElementById('show').addEventListener('click', function () {
    focusTrap.activate()
})

document.getElementById('hide').addEventListener('click', function () {
    focusTrap.deactivate()
})

甚至反应;

import React from 'react'
import ReactDOM from 'react-dom'
// Use the wrapper package of `focus-trap` to use with React.
import FocusTrap from 'focus-trap-react'

const Demo = () => {
    const [showModal, setShowModal] = React.useState(false)

    return (
        <div>
            <button onClick={() => setShowModal(true)}>show modal</button>

            <FocusTrap active={showModal}>
                <div id="modal">
                    Modal with <a href="#">with</a> <a href="#">some</a>{' '}
                    <a href="#">focusable</a> elements.
                    <button onClick={() => setShowModal(false)}>
                        hide modal
                    </button>
                </div>
            </FocusTrap>
        </div>
    )
}

ReactDOM.render(<Demo />, document.getElementById('demo'))

我在这里写了一篇关于这个包的小文章,解释了如何将它与 vanilla Javascript 或 React 一起使用。

于 2020-10-18T11:07:53.983 回答
0

问题之一是您使用keyup的是keydown. 只有在选项卡已经触发后,keyup 才会触发。但是,对代码进行更改会导致键盘被困在其中一个链接上。代码有缺陷。

这是一些你想要的代码(使用jQuery)

http://dylanb.github.io/javascripts/periodic-1.1.js

// Add keyboard handling for TAB circling

  $modal.on('keydown', function (e) {
    var cancel = false;
    if (e.ctrlKey || e.metaKey || e.altKey) {
      return;
    }
    switch(e.which) {
      case 27: // ESC
        $modal.hide();
        lastfocus.focus();
        cancel = true;
        break;
      case 9: // TAB
        if (e.shiftKey) {
          if (e.target === links[0]) {
            links[links.length - 1].focus();
            cancel = true;
          }
        } else {
          if (e.target === links[links.length - 1]) {
            links[0].focus();
            cancel = true;
          }
        }
        break;
    }
    if (cancel) {
      e.preventDefault();
    }
  });

您可以在此处查看此对话框的工作版本

http://dylanb.github.io/periodic-aria11-attributes.html

单击其中一个彩色框中的文本以查看弹出的对话框。

于 2015-10-07T16:14:03.937 回答