diff options
author | michaelvogt <michael@vaadin.com> | 2013-03-21 10:40:45 +0200 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2013-04-04 16:15:00 +0000 |
commit | f980667fdfef13bcb3bfcd7e86910bed39f39bb2 (patch) | |
tree | bddca5db6884e3a01c6d4455d9aff481d1b18e5c /client | |
parent | 3ee3b4926b1af4409b32196ef290baf017b63379 (diff) | |
download | vaadin-framework-f980667fdfef13bcb3bfcd7e86910bed39f39bb2.tar.gz vaadin-framework-f980667fdfef13bcb3bfcd7e86910bed39f39bb2.zip |
WAI-ARIA functions for Tree (#11389)
All to navigate the tree with an assisitve device
Change-Id: I531cefc95d7a720caf69aca579549e5a497ad586
Diffstat (limited to 'client')
-rw-r--r-- | client/src/com/vaadin/client/ui/VContextMenu.java | 2 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/VTree.java | 63 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/tree/TreeConnector.java | 7 |
3 files changed, 67 insertions, 5 deletions
diff --git a/client/src/com/vaadin/client/ui/VContextMenu.java b/client/src/com/vaadin/client/ui/VContextMenu.java index 80751652df..e601c8027a 100644 --- a/client/src/com/vaadin/client/ui/VContextMenu.java +++ b/client/src/com/vaadin/client/ui/VContextMenu.java @@ -37,6 +37,7 @@ import com.google.gwt.event.dom.client.LoadEvent; import com.google.gwt.event.dom.client.LoadHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.MenuBar; @@ -75,6 +76,7 @@ public class VContextMenu extends VOverlay implements SubPartAware { super(true, false, true); setWidget(menu); setStyleName("v-contextmenu"); + getElement().setId(DOM.createUniqueId()); } protected void imagesLoaded() { diff --git a/client/src/com/vaadin/client/ui/VTree.java b/client/src/com/vaadin/client/ui/VTree.java index 624dce4f13..20b3050a5d 100644 --- a/client/src/com/vaadin/client/ui/VTree.java +++ b/client/src/com/vaadin/client/ui/VTree.java @@ -24,6 +24,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import com.google.gwt.aria.client.ExpandedValue; +import com.google.gwt.aria.client.Id; +import com.google.gwt.aria.client.Roles; +import com.google.gwt.aria.client.SelectedValue; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; @@ -75,7 +79,8 @@ import com.vaadin.shared.ui.tree.TreeConstants; */ public class VTree extends FocusElementPanel implements VHasDropHandler, FocusHandler, BlurHandler, KeyPressHandler, KeyDownHandler, - SubPartAware, ActionOwner { + SubPartAware, ActionOwner, HandlesAriaCaption { + private String lastNodeKey = ""; public static final String CLASSNAME = "v-tree"; @@ -168,6 +173,8 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, public VTree() { super(); setStyleName(CLASSNAME); + + Roles.getTreeRole().set(body.getElement()); add(body); addFocusHandler(this); @@ -865,12 +872,22 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, } protected void constructDom() { + String labelId = DOM.createUniqueId(); + addStyleName(CLASSNAME); + getElement().setId(DOM.createUniqueId()); + Roles.getTreeitemRole().set(getElement()); + Roles.getTreeitemRole().setAriaSelectedState(getElement(), + SelectedValue.FALSE); + Roles.getTreeitemRole().setAriaLabelledbyProperty(getElement(), + Id.of(labelId)); nodeCaptionDiv = DOM.createDiv(); DOM.setElementProperty(nodeCaptionDiv, "className", CLASSNAME + "-caption"); Element wrapper = DOM.createDiv(); + wrapper.setId(labelId); + nodeCaptionSpan = DOM.createSpan(); DOM.appendChild(getElement(), nodeCaptionDiv); DOM.appendChild(nodeCaptionDiv, wrapper); @@ -886,6 +903,7 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, childNodeContainer = new FlowPanel(); childNodeContainer.setStyleName(CLASSNAME + "-children"); + Roles.getGroupRole().set(childNodeContainer.getElement()); setWidget(childNodeContainer); } @@ -914,10 +932,13 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, new String[] { key }, true); } addStyleName(CLASSNAME + "-expanded"); + Roles.getTreeitemRole().setAriaExpandedState(getElement(), + ExpandedValue.TRUE); childNodeContainer.setVisible(true); - } else { removeStyleName(CLASSNAME + "-expanded"); + Roles.getTreeitemRole().setAriaExpandedState(getElement(), + ExpandedValue.FALSE); childNodeContainer.setVisible(false); if (notifyServer) { client.updateVariable(paintableId, "collapse", @@ -1094,15 +1115,17 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, Util.scrollIntoViewVertically(nodeCaptionDiv); } - public void setIcon(String iconUrl) { + public void setIcon(String iconUrl, String altText) { if (iconUrl != null) { // Add icon if not present if (icon == null) { icon = new Icon(client); + Roles.getImgRole().set(icon.getElement()); DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), icon.getElement(), nodeCaptionSpan); } icon.setUri(iconUrl); + icon.getElement().setAttribute("alt", altText); } else { // Remove icon if present if (icon != null) { @@ -1517,10 +1540,34 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, // Unfocus previously focused node if (focusedNode != null) { focusedNode.setFocused(false); + + Roles.getTreeRole().removeAriaActivedescendantProperty( + focusedNode.getElement()); } if (node != null) { node.setFocused(true); + Roles.getTreeitemRole().setAriaSelectedState(node.getElement(), + SelectedValue.TRUE); + + /* + * FIXME: This code needs to be changed when the keyboard navigation + * doesn't immediately trigger a selection change anymore. + * + * Right now this function is called before and after the Tree is + * rebuilt when up/down arrow keys are pressed. This leads to the + * problem, that the newly selected item is announced too often with + * a screen reader. + * + * Behaviour is different when using the Tree with and without + * screen reader. + */ + if (node.key.equals(lastNodeKey)) { + Roles.getTreeRole().setAriaActivedescendantProperty( + getFocusElement(), Id.of(node.getElement())); + } else { + lastNodeKey = node.key; + } } focusedNode = node; @@ -2161,4 +2208,14 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, keyToNode.clear(); } + @Override + public void bindAriaCaption(Element captionElement) { + AriaHelper.bindCaption(body, captionElement); + } + + @Override + public void clearAriaCaption() { + AriaHelper.clearCaption(body); + } + } diff --git a/client/src/com/vaadin/client/ui/tree/TreeConnector.java b/client/src/com/vaadin/client/ui/tree/TreeConnector.java index 6e3fffb47c..d8ad7d6634 100644 --- a/client/src/com/vaadin/client/ui/tree/TreeConnector.java +++ b/client/src/com/vaadin/client/ui/tree/TreeConnector.java @@ -262,8 +262,11 @@ public class TreeConnector extends AbstractComponentConnector implements getWidget().selectedIds.add(nodeKey); } - treeNode.setIcon(uidl - .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON)); + String iconUrl = uidl + .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON); + String iconAltText = uidl + .getStringAttribute(TreeConstants.ATTRIBUTE_NODE_ICON_ALT); + treeNode.setIcon(iconUrl, iconAltText); } void renderChildNodes(TreeNode containerNode, Iterator<UIDL> i, int level) { |