summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authormichaelvogt <michael@vaadin.com>2013-03-21 10:40:45 +0200
committerVaadin Code Review <review@vaadin.com>2013-04-04 16:15:00 +0000
commitf980667fdfef13bcb3bfcd7e86910bed39f39bb2 (patch)
treebddca5db6884e3a01c6d4455d9aff481d1b18e5c /client
parent3ee3b4926b1af4409b32196ef290baf017b63379 (diff)
downloadvaadin-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.java2
-rw-r--r--client/src/com/vaadin/client/ui/VTree.java63
-rw-r--r--client/src/com/vaadin/client/ui/tree/TreeConnector.java7
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) {