手风琴组件键盘命令
Accordion component keyboard commands
我有一个手风琴组件,它使用 'tab' 在控件中导航,并且在 'enter' 和 'spacebar' 上手风琴展开。我正在尝试找出一种使用 'up' 和 'down' 箭头键导航到下一个手风琴的方法。我熟悉 Javascript 但我无法使用现有代码实现此目的。非常感谢我能得到的任何帮助。
这是我的手风琴组件的 CodePen。 https://codepen.io/ozman2182/pen/vYgvGOd
(function () {
const headings = document.querySelectorAll(".unr-accordion--heading");
Array.prototype.forEach.call(headings, (h) => {
let btn = h.querySelector("button");
let target = h.nextElementSibling;
btn.onclick = () => {
let expanded = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
};
});
})();
请原谅我的 JS 老派 - 我仍然支持 IE9
在此答案末尾的示例中,我添加了使箭头键在列表中上下循环(并循环)所需的代码。
我还添加了 Home
和 End
键以转到列表的开头和结尾(这是预期的行为)。
总而言之,我们:
- 用
.querySelectorAll('.unr-accordion--heading>button');
抓住所有按钮
- 为“keydown”添加一个事件侦听器
- 查看
keyCode
是 38(向上)还是 40(向下),如果是,我们应用 -1(在我们的按钮列表中向上移动一个项目)或 + 的“方向” 1(向下)。
- 如果 keyCode 是 36(“Home”)- 我们将方向设置为 -999,以便稍后查看
- 如果 keyCode 为 35(“结束”)- 我们将方向设置为 999,以便稍后查看
- 如果设置了方向(按下向上或向下箭头或主页/结束),我们将遍历所有按钮。
- 如果循环当前阶段的按钮等于
document.activeElement
(当前聚焦的项目),那么我们知道我们既在手风琴中又在按钮上,箭头键应该起作用。
- 然后我们检查方向是否向上并且我们关注按钮列表中的第一项 (
direction == -1 && x == 0
) 或者“方向”是否为 -999(主页键),因此我们可以循环到按钮列表的底部并聚焦那个按钮。如果是这样,我们使用 break;
退出循环
- 如果不是,那么我们检查方向是否向下并且我们关注按钮列表中的最后一项(
direction == 1 && x == max
)或者“方向”是否为 +999(结束键),所以我们可以循环到按钮列表的顶部并聚焦那个按钮。如果是这样,我们使用 break;
退出循环
- 最后,如果以上都不成立,我们只需按方向移动焦点(-1 向上,+1 向下),然后退出循环。
(function () {
const headings = document.querySelectorAll(".unr-accordion--heading");
Array.prototype.forEach.call(headings, (h) => {
let btn = h.querySelector("button");
let target = h.nextElementSibling;
btn.onclick = () => {
let expanded = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
};
});
var btns = document.querySelectorAll('.unr-accordion--heading>button');
document.addEventListener('keydown', function(e){
var direction = 0;
var max = btns.length - 1;
direction = (e.keyCode == 38) ? -1 : direction;
direction = (e.keyCode == 40) ? 1 : direction;
direction = (e.keyCode == 35) ? -999 : direction;
direction = (e.keyCode == 36) ? 999 : direction;
if(direction != ""){
e.preventDefault();
for(x = 0; x <= max; x++){
if(document.activeElement == btns[x]){
if(direction == -1 && x == 0 || direction == -999){
btns[max].focus();
break;
}
if(direction == 1 && x == max || direction == 999){
btns[0].focus();
break;
}
btns[x + direction].focus();
break;
}
}
}
})
})();
:root {
--blue-10: #E6E9EC;
--blue-20: #CDD2D9;
--blue-50: #828FA1;
--blue-80: #364B68;
--blue-100: #041E42;
}
html {
font-family: Helvetica, sans-serif;
color: var(--blue-100);
}
section {
max-width: 920px;
margin-top: 3em;
margin-right: auto;
margin-left: auto;
}
.unr-accordion--expandall {
margin-bottom: 1em;
border:2px solid var(--blue-20);
border-radius: 5px;
padding: 0.5em 1em;
background-color: white;
}
.unr-accordion--expandall:hover,
.unr-accordion--expandall:focus {
border:2px solid var(--blue-10);
background-color: var(--blue-10);
}
.unr-accordion--wrapper {
border: 2px solid var(--blue-20);
border-radius: 5px;
margin-bottom: 0.5em;
}
.unr-accordion--wrapper:last-child {
margin-bottom: 0;
}
.unr-accordion--wrapper > h2 {
display: flex;
margin: 0;
border-radius: 5px;
}
.unr-accordion--wrapper > h2 button {
all: inherit;
border: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin: 0;
padding: 0.5em;
font-size: 1.5rem;
line-height: 1.5;
}
.unr-accordion--wrapper > h2 button:hover {
background-color: var(--blue-10);
}
.unr-accordion--wrapper > h2 button svg {
font-size: 1rem;
margin-left: 0.5em;
flex-shrink: 0;
}
.unr-accordion--wrapper > h2 button:focus svg {
outline: 2px solid;
}
.unr-accordion--wrapper > h2 button[aria-expanded="true"] {
background-color: var(--blue-10);
}
.unr-accordion--wrapper > h2 button[aria-expanded="true"] .vert {
display: none;
}
.unr-accordion--wrapper > h2 button[aria-expanded] rect {
fill: currentColor;
}
.unr-accordion--panel {
margin-top: -1em;
padding-top: 1em;
padding-right: 1em;
padding-bottom: 1em;
padding-left: 1em;
background-color: var(--blue-10);
}
<section>
<h1>Edgar Allan Poe was an American writer, poet, editor, and literary critic.</h1>
<p>Poe is best known for his poetry and short stories, particularly his tales of mystery and the macabre. He is widely regarded as a central figure of Romanticism in the United States and of American literature as a whole, and he was one of the country's earliest practitioners of the short story.</p>
<!-- <button class="unr-accordion--expandall" href="#">Expand All</button> -->
<!-- accordion items -->
<div class="unr-accordions">
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Black Cat (short story)
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>It was first published in the August 19, 1843, edition of The Saturday Evening Post. In the story, an unnamed narrator has a strong affection for pets until he perversely turns to abusing them.</p>
</div>
</div>
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Cask of Amontillado
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>First published in the November 1846 issue of Godey's Lady's Book. The story, set in an unnamed Italian city at carnival time in an unspecified year, is about a man taking fatal revenge on a friend who, he believes, has insulted him. Like several of Poe's stories, and in keeping with the 19th-century fascination with the subject, the narrative revolves around a person being buried alive – in this case, by immurement. As in "The Black Cat" and "The Tell-Tale Heart", Poe conveys the story from the murderer's perspective.</p>
</div>
</div>
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Gold-Bug
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>The plot follows William Legrand, who was bitten by a gold-colored bug. His servant Jupiter fears that Legrand is going insane and goes to Legrand's friend, an unnamed narrator, who agrees to visit his old friend. Legrand pulls the other two into an adventure after deciphering a secret message that will lead to a buried treasure. </p>
</div>
</div>
</div>
</div>
<!-- end: accordion component -->
</section>
我有一个手风琴组件,它使用 'tab' 在控件中导航,并且在 'enter' 和 'spacebar' 上手风琴展开。我正在尝试找出一种使用 'up' 和 'down' 箭头键导航到下一个手风琴的方法。我熟悉 Javascript 但我无法使用现有代码实现此目的。非常感谢我能得到的任何帮助。
这是我的手风琴组件的 CodePen。 https://codepen.io/ozman2182/pen/vYgvGOd
(function () {
const headings = document.querySelectorAll(".unr-accordion--heading");
Array.prototype.forEach.call(headings, (h) => {
let btn = h.querySelector("button");
let target = h.nextElementSibling;
btn.onclick = () => {
let expanded = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
};
});
})();
请原谅我的 JS 老派 - 我仍然支持 IE9
在此答案末尾的示例中,我添加了使箭头键在列表中上下循环(并循环)所需的代码。
我还添加了 Home
和 End
键以转到列表的开头和结尾(这是预期的行为)。
总而言之,我们:
- 用
.querySelectorAll('.unr-accordion--heading>button');
抓住所有按钮
- 为“keydown”添加一个事件侦听器
- 查看
keyCode
是 38(向上)还是 40(向下),如果是,我们应用 -1(在我们的按钮列表中向上移动一个项目)或 + 的“方向” 1(向下)。 - 如果 keyCode 是 36(“Home”)- 我们将方向设置为 -999,以便稍后查看
- 如果 keyCode 为 35(“结束”)- 我们将方向设置为 999,以便稍后查看
- 如果设置了方向(按下向上或向下箭头或主页/结束),我们将遍历所有按钮。
- 如果循环当前阶段的按钮等于
document.activeElement
(当前聚焦的项目),那么我们知道我们既在手风琴中又在按钮上,箭头键应该起作用。 - 然后我们检查方向是否向上并且我们关注按钮列表中的第一项 (
direction == -1 && x == 0
) 或者“方向”是否为 -999(主页键),因此我们可以循环到按钮列表的底部并聚焦那个按钮。如果是这样,我们使用break;
退出循环
- 如果不是,那么我们检查方向是否向下并且我们关注按钮列表中的最后一项(
direction == 1 && x == max
)或者“方向”是否为 +999(结束键),所以我们可以循环到按钮列表的顶部并聚焦那个按钮。如果是这样,我们使用break;
退出循环
- 最后,如果以上都不成立,我们只需按方向移动焦点(-1 向上,+1 向下),然后退出循环。
(function () {
const headings = document.querySelectorAll(".unr-accordion--heading");
Array.prototype.forEach.call(headings, (h) => {
let btn = h.querySelector("button");
let target = h.nextElementSibling;
btn.onclick = () => {
let expanded = btn.getAttribute("aria-expanded") === "true";
btn.setAttribute("aria-expanded", !expanded);
target.hidden = expanded;
};
});
var btns = document.querySelectorAll('.unr-accordion--heading>button');
document.addEventListener('keydown', function(e){
var direction = 0;
var max = btns.length - 1;
direction = (e.keyCode == 38) ? -1 : direction;
direction = (e.keyCode == 40) ? 1 : direction;
direction = (e.keyCode == 35) ? -999 : direction;
direction = (e.keyCode == 36) ? 999 : direction;
if(direction != ""){
e.preventDefault();
for(x = 0; x <= max; x++){
if(document.activeElement == btns[x]){
if(direction == -1 && x == 0 || direction == -999){
btns[max].focus();
break;
}
if(direction == 1 && x == max || direction == 999){
btns[0].focus();
break;
}
btns[x + direction].focus();
break;
}
}
}
})
})();
:root {
--blue-10: #E6E9EC;
--blue-20: #CDD2D9;
--blue-50: #828FA1;
--blue-80: #364B68;
--blue-100: #041E42;
}
html {
font-family: Helvetica, sans-serif;
color: var(--blue-100);
}
section {
max-width: 920px;
margin-top: 3em;
margin-right: auto;
margin-left: auto;
}
.unr-accordion--expandall {
margin-bottom: 1em;
border:2px solid var(--blue-20);
border-radius: 5px;
padding: 0.5em 1em;
background-color: white;
}
.unr-accordion--expandall:hover,
.unr-accordion--expandall:focus {
border:2px solid var(--blue-10);
background-color: var(--blue-10);
}
.unr-accordion--wrapper {
border: 2px solid var(--blue-20);
border-radius: 5px;
margin-bottom: 0.5em;
}
.unr-accordion--wrapper:last-child {
margin-bottom: 0;
}
.unr-accordion--wrapper > h2 {
display: flex;
margin: 0;
border-radius: 5px;
}
.unr-accordion--wrapper > h2 button {
all: inherit;
border: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin: 0;
padding: 0.5em;
font-size: 1.5rem;
line-height: 1.5;
}
.unr-accordion--wrapper > h2 button:hover {
background-color: var(--blue-10);
}
.unr-accordion--wrapper > h2 button svg {
font-size: 1rem;
margin-left: 0.5em;
flex-shrink: 0;
}
.unr-accordion--wrapper > h2 button:focus svg {
outline: 2px solid;
}
.unr-accordion--wrapper > h2 button[aria-expanded="true"] {
background-color: var(--blue-10);
}
.unr-accordion--wrapper > h2 button[aria-expanded="true"] .vert {
display: none;
}
.unr-accordion--wrapper > h2 button[aria-expanded] rect {
fill: currentColor;
}
.unr-accordion--panel {
margin-top: -1em;
padding-top: 1em;
padding-right: 1em;
padding-bottom: 1em;
padding-left: 1em;
background-color: var(--blue-10);
}
<section>
<h1>Edgar Allan Poe was an American writer, poet, editor, and literary critic.</h1>
<p>Poe is best known for his poetry and short stories, particularly his tales of mystery and the macabre. He is widely regarded as a central figure of Romanticism in the United States and of American literature as a whole, and he was one of the country's earliest practitioners of the short story.</p>
<!-- <button class="unr-accordion--expandall" href="#">Expand All</button> -->
<!-- accordion items -->
<div class="unr-accordions">
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Black Cat (short story)
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>It was first published in the August 19, 1843, edition of The Saturday Evening Post. In the story, an unnamed narrator has a strong affection for pets until he perversely turns to abusing them.</p>
</div>
</div>
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Cask of Amontillado
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>First published in the November 1846 issue of Godey's Lady's Book. The story, set in an unnamed Italian city at carnival time in an unspecified year, is about a man taking fatal revenge on a friend who, he believes, has insulted him. Like several of Poe's stories, and in keeping with the 19th-century fascination with the subject, the narrative revolves around a person being buried alive – in this case, by immurement. As in "The Black Cat" and "The Tell-Tale Heart", Poe conveys the story from the murderer's perspective.</p>
</div>
</div>
<div class="unr-accordion--wrapper">
<h2 class="unr-accordion--heading">
<button aria-expanded="false">
The Gold-Bug
<svg viewbox="0 0 10 10" width="24px" height="24px" aria-hidden="true" focusable="false">
<rect class="vert" height="8" width="2" y="1" x="4" />
<rect height="2" width="8" y="4" x="1" />
</svg>
</button>
</h2>
<div class="unr-accordion--panel" hidden>
<p>The plot follows William Legrand, who was bitten by a gold-colored bug. His servant Jupiter fears that Legrand is going insane and goes to Legrand's friend, an unnamed narrator, who agrees to visit his old friend. Legrand pulls the other two into an adventure after deciphering a secret message that will lead to a buried treasure. </p>
</div>
</div>
</div>
</div>
<!-- end: accordion component -->
</section>