香草javascript Trap Focus in modal(辅助功能标签)

时间:2015-10-07 15:49:34

标签: javascript focus accessibility tabbing

这应该很简单但是由于某些原因它不起作用,我在正确的时间获得了正确的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);

3 个答案:

答案 0 :(得分:1)

我必须将焦点锁定在我们在React组件中使用的模式中。 我添加了用于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]();
        }
    }
}

答案 1 :(得分: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>

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

答案 2 :(得分:0)

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

您可以使用原始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()
})

甚至是React;

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'))

我做了一个关于软件包here的小写,它解释了如何将其与原始Javascript或React结合使用。