#javascript #html #wai-aria #web-accessibility
#javascript #HTML #Специальные возможности #вай-ария
Вопрос:
Итак, у меня есть несколько div
файлов, расположенных один под другим. Я хочу, чтобы они были «доступны через Интернет» с помощью клавиш со стрелками, то есть, если я нажму клавишу down, следующая div
должна быть выделена, а если я нажму клавишу up, должна быть выделена предыдущая.
Если бы у меня была кнопка, я мог бы использовать tabIndex
свойство для ее достижения.
Дело в том, что div
s не являются элементами, подлежащими действию. Так что это может сбить с толку пользователей, если я каким-то образом сделаю их доступными через вкладки. Следовательно, я хочу это только с помощью клавиш со стрелками на клавиатуре.
Я даже готов преобразовать его в <ul><li><li></ul>
, если можно добиться желаемого поведения.
<div>Div 1</div>
<div>Div 2</div>
<div>Div 3</div>
<div>Div 4</div>
Это то, что я пробовал с <li>
s. Но если я нажму на первый li
, я не могу перейти и выделить следующий, нажав стрелку вниз.
<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>
Комментарии:
1. Пожалуйста, определите «доступный div».
2. @Teemu Accessibility (веб-доступность) — доступно для пользователей с различными возможностями, которые используют клавиатуру для навигации или для чтения содержимого страницы.
3. Но что это означает на практике? Вы хотите выделить div или просто прокрутить до него или что-то еще?
4. Затем преобразуйте их в ul lis
5. @Teemu да, выделения достаточно.
Ответ №1:
Существует виджет ARIA, который позволяет осуществлять навигацию с клавиатуры с помощью клавиш со стрелками, с одной остановкой табуляции вместо многих: ваш список похожих <div>
файлов может быть сформирован в виде сетки с одним столбцом.
Изначально будет получена ячейка в первой строке tabindex="0"
, а все остальные — tabindex="-1"
.
Используя JavaScript, наведение стрелки вниз фокусирует ячейку во второй строке. Оно выполняется tabindex="0"
одновременно с получением ячейки в первой строке tabindex="-1"
, так что остается только одна ячейка, доступная для табуляции / фокусировки. Полная обработка клавиатуры указана в примерах / документах.
В JavaScript вам нужно будет отслеживать текущий элемент, на котором сосредоточен.
Вот как я бы настроил это с помощью 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')
)
Комментарии:
1. Учитывая, что OP не помечен и не упомянут React, насколько точно вы представляете, насколько уместен этот ответ?
2. @floodlitworld В комментарии спрашивает, доступна ли версия ответа на jQuery в React, поэтому я использовал React, чтобы приблизить их к тому, что они могли бы использовать. Я не думаю, что это заслуживает понижения.
Ответ №2:
Привет, вы должны использовать jquery для того, что вы хотите. Вашим последним источником будет это:
$(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>
Я надеюсь, что это будет полезно.
Комментарии:
1. Хм, я вижу это. Я хотел избежать jquery / javascript. Но, похоже, это единственный способ. Кстати, есть идеи, как это сделать с помощью react-hooks?
2. У вас есть другой способ, и вы можете написать комментарий под своим списком и сказать, используйте «Кнопку табуляции, чтобы изменить выбранную строку». Но я не знаю react и понятия не имею об этом!
3. Не беспокойтесь. Для этого я свяжу события keyup и key down в react. Дело в том, что для достижения этого нам придется перехватывать события нажатия клавиш.