Richfaces通过箭头键(左,右,上,下),选项卡和输入进行树导航

时间:2014-05-15 11:01:39

标签: jsf richfaces keycode

我有一个工作正常的树组件。但是,我们希望让应用程序对残障人士更加友好。该应用应该使用户能够:

  • 使用箭头键(向上/向下)和Tab键
  • 导航treenodes
  • 移动到节点使其成为选定/聚焦节点
  • 在所选节点上,用于展开节点的右箭头键和输入键显示上下文菜单

这是我当前的树组件,它可以正常工作:

 <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>

我已经检查了解决方案here,但大多数都建议使用服务器端处理和事件处理。有没有办法可以完全在客户端完成?

2 个答案:

答案 0 :(得分:1)

切换节点很简单,每个节点都有toggle()方法,您可以像这样切换当前节点:

tree.getSelection().getNodes()[0].toggle()

另一方面,穿越树是相当困难的。树保留对节点集的引用,但不保留对整个结构的引用 - 即,没有简单的方法来判断哪个节点应该是下一个节点。 jQuery可能会帮助你。

$('.rf-trn-cnt')

这将返回所有节点的列表,然后您可以在节点上调用mousedown()来选择它。

答案 1 :(得分:0)

对于有不适感的用户友好的Web应用程序可能包含外部导航组件,这使得导航<rich:tree>更简单。您可以考虑使用向导式按钮:上一步 / 下一步扩展相关分支并在订单中选择它们。

要实现此类组件,您需要与服务器进行一些通信。

我会保留所有可能的选项,以便在列表中上一页 / 下一步 <( 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:

Interactions with RichTree