简体   繁体   English

我如何制作 div 或<li>通过向上/向下箭头键访问</li>

[英]How do I make div or <li> accessible through Up/down arrow keys

So I have a few div s one below the other.所以我在另一个下面有几个div I want them to be "web accessible" via arrows keys, ie, if I press the down key next div should be highlighted and if I press the up key, the previous one should be highlighted.我希望它们可以通过箭头键“访问网络”,即,如果我按下向下键,则应突出显示下一个div ,如果按下向上键,则应突出显示前一个。

If I had a button I could have used the tabIndex property to achieve it.如果我有一个按钮,我可以使用tabIndex属性来实现它。

The thing is div s are not actionable items.问题是div不是可操作的项目。 So it could be confusing for the users if I make them somehow accessible through tabs.因此,如果我让他们以某种方式通过选项卡访问,可能会让用户感到困惑。 Hence, I want it only through arrow keys of the keyboard.因此,我只希望通过键盘的箭头键。

I'm even willing to convert it into <ul><li><li></ul> if the desired behavior could be achieved.如果可以实现所需的行为,我什至愿意将其转换为<ul><li><li></ul>

 <div>Div 1</div> <div>Div 2</div> <div>Div 3</div> <div>Div 4</div>

This is what I tried with <li> s.这就是我尝试使用<li>的方法。 But If I click on the first li I cant go and highlight the next one by pressing the down arrow.但是如果我点击第一个li我不能 go 并通过按向下箭头突出显示下一个。

 <ul role="menu" aria-label="menu"> <li role="menuitem" tabindex="0">list 1</li> <li role="menuitem" tabindex="0">list 2</li> <li role="menuitem" tabindex="0">list 3</li> <li role="menuitem" tabindex="0">list 4</li> <li role="menuitem" tabindex="0">list 5</li> </ul>

There is an ARIA widget that allows for keyboard navigation via arrow keys, with one tab stop instead of many: your list of similar <div> s can be formulated as a single-column Grid .有一个 ARIA 小部件允许通过箭头键进行键盘导航,使用一个制表位而不是多个制表位:您的类似<div>列表可以表示为单列Grid

Initially, the cell in the first row gets tabindex="0" and all others get tabindex="-1" .最初,第一行中的单元格得到tabindex="0" ,所有其他单元格得到tabindex="-1"

Using JavaScript, arrowing down focuses the cell in the second row.使用 JavaScript,向下箭头聚焦第二行中的单元格。 It gets tabindex="0" while the cell in the first row gets tabindex="-1" , so that there is only ever one cell that is tabbable/focusable.它得到tabindex="0"而第一行中的单元格得到tabindex="-1" ,因此只有一个单元格是可选项卡/可聚焦的。 The full keyboard handling is specified in the examples/docs .完整的键盘处理在examples/docs中指定。

In JavaScript, you will need to keep track of currently focused item.在 JavaScript 中,您需要跟踪当前关注的项目。

Here's how I would set it up using React:以下是我使用 React 进行设置的方法:

class MyGrid extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            focusedItemIndex: 0
        }

        this.cellRefs = []

        this.handleFocus = (index => {
            this.setState(() => ({
                focusedItemIndex: index
            }))
        }).bind(this)

        this.handleKeydown = ((index, {
            key
        }) => {
            switch (key) {
                case 'ArrowUp': {
                    this.setState(() => ({
                        focusedItemIndex: Math.max(0, index - 1)
                    }))
                }
                break
                case 'ArrowDown': {
                    this.setState(() => ({
                        focusedItemIndex: Math.min(index + 1, this.props.items.length - 1)
                    }))
                }
                break
                case 'Home': {
                    this.setState(() => ({
                        focusedItemIndex: 0
                    }))
                }
                break
                case 'End': {
                    this.setState(() => ({
                        focusedItemIndex: this.props.items.length - 1
                    }))
                }
                break
                default: {
                    return
                }
            }
        }).bind(this)
    }
    componentDidUpdate(_, prevState) {
        if (prevState.focusedItemIndex !== this.state.focusedItemIndex) {
            this.cellRefs[this.state.focusedItemIndex].focus()
        }
    }
    render() {
        return (
            <div
                role="grid"
                aria-label="This needs a label">
                <div role="row">
                    {this.props.items.map((item, index) => (
                        <div
                            role="cell"
                            key={item}
                            ref={el => this.cellRefs[index] = el}
                            tabIndex={this.state.focusedItemIndex === index ? '0' : '-1'}
                            onFocus={this.handleFocus.bind(this, index)}
                            onKeyDown={this.handleKeydown.bind(this, index)}>
                            {item}
                        </div>
                    ))}
                </div>
            </div>
        )
    }
}

ReactDOM.render(
    <MyGrid items={['A', 'B', 'C']} />,
    document.querySelector('body')
)

Hi you should use jquery for what you want.嗨,您应该使用 jquery 来满足您的需求。 Your last source will be this:您的最后一个来源将是:

 $(function(){ document.onkeydown = function(e) { var selected = $('.mnu-item:focus').index(); var next = selected + 1; var pre = selected - 1; if(pre < 0) pre = 0; if(next > $('.mnu-item').length) next = $('.mnu-item').length; if(e.which == 38) { // up $('.mnu-item').eq(pre).focus(); } if(e.which == 40) { // down $('.mnu-item').eq(next).focus(); } e.preventDefault(); // prevent the default action (scroll / move caret) }; })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <ul role="menu" aria-label="menu"> <li role="menuitem" tabindex="0" class="mnu-item">list 1</li> <li role="menuitem" tabindex="0" class="mnu-item">list 2</li> <li role="menuitem" tabindex="0" class="mnu-item">list 3</li> <li role="menuitem" tabindex="0" class="mnu-item">list 4</li> <li role="menuitem" tabindex="0" class="mnu-item">list 5</li> </ul>

I hope this will be useful.我希望这会有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM