问题描述
treeview example的WAI-ARIA Authoring Practices展示了如何创建一棵树,其中有些项目是可扩展的父节点,有些是超链接:
<ul role="tree" aria-label="Foods">
<li role="treeitem" aria-expanded="true">
<span> Fruits </span>
<ul role="group">
<li role="none"> <a role="treeitem" href="/orange"> Oranges </a> </li>
<li role="none"> <a role="treeitem" href="/pineapple"> Pineapple </a> </li>
</ul>
</li>
</ul>
但是,如果我也想有一个“水果”页面,并且有一个既是父节点又是超链接的树项目怎么办?
(对于键盘导航,将使用Right Arrow
/ Left Arrow
打开/关闭父节点,并在超链接之后使用Enter
的模式。这类似于combobox with a tree popup的交互。
对于鼠标交互,将保留当前模式:具有一个可单击图标(aria-hidden
),该图标指示展开状态(打开/关闭该节点),链接本身的文本位于该链接之后。)
例如:
<ul role="tree" aria-label="Foods">
<li role="none">
<a role="treeitem" aria-expanded="true" href="/fruits">
<span> Fruits </span>
<ul role="group">
<li role="none"> <a role="treeitem" href="/orange"> Oranges </a> </li>
<li role="none"> <a role="treeitem" href="/pineapple"> Pineapple </a> </li>
</ul>
</a>
</li>
</ul>
这在技术上是正确的,但违反了HTML规范,该规范不允许将<a>
标签嵌套在其他<a>
标签中。
解决方法
经过大量搜索,我发现this answer是关于另一个主题的,仅暗示了我的解决方案。
要使<a>
元素成为treeitem
,而同时“包含”嵌套在组中的其他<a>
元素,则可以使用aria-owns
属性。
像这样,要求
每个父节点包含或拥有一个具有角色组的元素。
很满意,同时符合HTML规范。
<ul role="tree" aria-label="Foods">
<li role="none">
<a role="treeitem" aria-expanded="true" aria-owns="fruit-group" href="/fruits">
<span> Fruits </span>
</a>
<ul role="group" id="fruit-group">
<li role="none"> <a role="treeitem" href="/orange"> Oranges </a> </li>
<li role="none"> <a role="treeitem" href="/pineapple"> Pineapple </a> </li>
</ul>
</li>
</ul>
,
这不完全是您要找的东西,但我想我会与任何正在寻找至少从最终用户的角度完成相同事情的类似东西的人分享它。
以下代码已从 w3school 的 Tree View Example 修改为除了它们之外还有可点击的箭头和父链接项。
原始代码:https://www.w3schools.com/howto/howto_js_treeview.asp
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
ul,#myUL {
list-style-type: none;
}
#myUL {
margin: 0;
padding: 0;
}
.caret {
cursor: pointer;
-webkit-user-select: none; /* Safari 3.1+ */
-moz-user-select: none; /* Firefox 2+ */
-ms-user-select: none; /* IE 10+ */
user-select: none;
}
.caret::before {
content: "\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
.caret-down::before {
-ms-transform: rotate(90deg); /* IE 9 */
-webkit-transform: rotate(90deg); /* Safari */'
transform: rotate(90deg);
}
.nested {
display: none;
}
.active {
display: block;
}
</style>
</head>
<body>
<h2>Tree View</h2>
<p>A tree view represents a hierarchical view of information,where each item can have a number of subitems.</p>
<p>Click on the arrow(s) to open or close the tree branches.</p>
<ul id="myUL">
<li><span class="caret"><a href="https://en.wikipedia.org/wiki/Drink">Beverages</a></span>
<ul class="nested">
<li><a href="https://en.wikipedia.org/wiki/Water">Water</a></li>
<li><span class="caret">Juice</span>
<ul class="nested">
<li>Orange Juice</li>
<li>Apple Juice</li>
</ul>
</li> <!-- End of caret Tea -->
<li><span class="caret">Tea</span>
<ul class="nested">
<li>Black Tea</li>
<li>White Tea</li>
<li><span class="caret"></span><a href="https://en.wikipedia.org/wiki/Green_tea">Green Tea</a>
<ul class="nested">
<li>Sencha</li>
<li>Gyokuro</li>
<li>Matcha</li>
<li>Pi Lo Chun</li>
</ul>
</li>
</ul>
</li> <!-- End of caret Tea -->
</ul> <!-- End of nested -->
</li> <!-- End of caret Beverage -->
</ul> <!-- End of myUL -->
<script>
var toggler = document.getElementsByClassName("caret");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click",function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
</script>
</body>
</html>