我有一个工作良好的树组件。然而,我们想让这个应用程序对残疾人更友好。应用程序应该允许用户:
- 使用方向键(向上/向下)和tab键浏览三极
- 移动到一个节点使其成为被选中/聚焦的节点
- 在选中的节点上,按右箭头键展开节点,按回车键显示上下文菜单
这是我当前的树组件,工作正常:
<rich:tree id="fileTree" var="item" selection="#{FILES.selection}" binding="#{FILES.binding}"
rightClickSelection="true" toggleType="ajax" selectionType="ajax" render="fileTree"
oncomplete="set_resource_updated(#{FILES.selected});"
onmousedown="var_allow_select = mouse_right_click(event);" onbeforeselectionchange="return var_allow_select;" >
<rich:treeModelRecursiveAdaptor roots="#{FILES.list}" nodes="#{item.directories}" leaf="#{not item.directory}">
<rich:treeNode expanded="#{item.expanded}" render="fileTree" >
<a href="#" class="treelnk" >
<a4j:outputPanel id="itemP1" >
<h:outputText value="#{item.name}" style="font-weight: #{item eq FILES.selectedNode ? 'bold':'normal'};"/>
<rich:dragSource dragValue="#{item}" type="typeT1" dragIndicator="fileI1"/>
<rich:dropTarget dropValue="#{item}" acceptedTypes="typeT1,typeT2" execute="itemP1,itemP2"
dropListener="#{FILES.dropListener}" immediate="true" render="popupDragDrop" oncomplete="#{rich:component('popupDragDrop')}.show()"/>
</a4j:outputPanel>
<rich:dragIndicator id="fileI1" acceptClass="accept" rejectClass="reject" draggingClass="default">
<h:outputText value="#{item.name}" style="padding-left: 10px"/>
</rich:dragIndicator>
</a>
</rich:treeNode>
<rich:treeModelAdaptor nodes="#{item.files}">
<rich:treeNode expanded="#{item.expanded}" render="fileTree" >
<a href="#" class="treelnk" >
<a4j:outputPanel id="itemP2" styleClass="panel">
<h:outputText value="#{item.name}" style="font-weight: #{item eq FILES.selectedNode ? 'bold':'normal'};"/>
<rich:dragSource dragValue="#{item}" type="typeT2" dragIndicator="fileI2"/>
<rich:dropTarget dropValue="#{item}" acceptedTypes="typeT1,typeT2" execute="itemP1,itemP2"
dropListener="#{FILES.dropListener}" immediate="true" render="popupDragDrop" oncomplete="#{rich:component('popupDragDrop')}.show()"/>
</a4j:outputPanel>
<rich:dragIndicator id="fileI2" acceptClass="accept" rejectClass="reject" draggingClass="default">
<h:outputText value="#{item.name}" style="padding-left: 10px; "/>
</rich:dragIndicator>
</a>
</rich:treeNode>
</rich:treeModelAdaptor>
</rich:treeModelRecursiveAdaptor>
</rich:tree>
我在这里检查了解决方案,但大多数建议服务器端处理和事件处理。有没有一种方法可以完全在客户端完成?
切换节点很容易,每个节点都有一个toggle()
方法,您可以像这样切换当前节点:
tree.getSelection().getNodes()[0].toggle()
另一方面,遍历树是相当困难的。树保留了对节点集的引用,而不是对整个结构的引用——也就是说,没有简单的方法来判断哪个节点应该是下一个选择的节点。jQuery可能会帮到你。
$('.rf-trn-cnt')
返回所有节点的列表,然后您可以在节点上调用mousedown()
来选择它。
为残障人士设计的用户友好的web应用程序可以由外部导航组件组成,这样可以更简单地导航<rich:tree>
。您可以考虑使用向导样式的按钮:prev/next展开相关分支并按顺序选择它们。
要实现这样的组件,您需要与服务器进行一些通信。
我将保留所有可能的导航选择prev/next在列表中(flatTraversalOrder):
@ManagedBean
@ViewScoped
public class TreeNavigator {
private List<SequenceRowKey> flatTraversalOrder;
@ManagedProperty("#{treeBean}")
private YourTreeBean treeBean;
@PostConstruct
public void initialize() {
flatTraversalOrder = createTraversalOrder(treeBean.getRootNode());
}
// Put desired nodes in desired order here, e.g. all children of root:
private List<SequenceRowKey> createTraversalOrder(YourTreeNode rootNode) {
List<SequenceRowKey> result = new ArrayList<>();
for (Iterator<Object> i = rootNode.getChildrenKeysIterator(); i.hasNext();) {
result.add(new SequenceRowKey(i.next()));
}
return result;
}
public void selectNext() {
List<Object> selectionList = new ArrayList<>(treeBean.getSelection());
SequenceRowKey selectionKey = (SequenceRowKey) selectionList.get(0);
int indexInTraversalList = flatTraversalOrder.indexOf(selectionKey);
if ((indexInTraversalList == -1) || (indexInTraversalList == flatTraversalOrder.size() - 1)) {
return;
}
SequenceRowKey toBeSelectedKey = flatTraversalOrder.get(indexInTraversalList + 1);
treeBean.getSelection().clear();
treeBean.getSelection().add(toBeSelectedKey);
}
}
selectNext()可以从大下一个按钮调用或由键盘事件触发。
树豆:
@ManagedBean
@ViewScoped
public class YourTreeBean {
private YourTreeNode rootNode;
private Collection<Object> selection;
//getters and setters
}
我已经实现了一个应用程序,在这个应用程序中,如果选择进入它们内部,我还会扩展节点。你可以在这里找到工作示例,描述和GitHub repo:
与RichTree的交互