Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion user/src/com/google/gwt/user/cellview/client/CellTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,9 @@ interface BasicStyle extends Style {
}

interface Template extends SafeHtmlTemplates {
@Template("<div class=\"{0}\" style=\"{1}position:absolute;\">{2}</div>")
// The open/closed/loading image is decorative; aria-expanded conveys the open/closed state.
@Template("<div class=\"{0}\" style=\"{1}position:absolute;\" aria-hidden=\"true\">"
+ "{2}</div>")
SafeHtml imageWrapper(String classes, SafeStyles cssLayout, SafeHtml image);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,11 @@ Element ensureAnimationFrame() {
Element ensureChildContainer() {
if (childContainer == null) {
childContainer = Document.get().createDivElement();
// Nested items need a group between them and their parent item; the root's
// children are owned by the tree element itself.
if (!isRootNode()) {
Roles.getGroupRole().set(childContainer);
}
ensureContentContainer().insertFirst(childContainer);
}
return childContainer;
Expand Down
51 changes: 51 additions & 0 deletions user/test/com/google/gwt/user/cellview/client/CellTreeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.RootPanel;
Expand Down Expand Up @@ -267,6 +269,55 @@ public void testAriaAttributes() {
assertEquals("5", cViewChildLast.getElement().getAttribute("aria-setsize"));
}

public void testChildContainerRoles() {
CellTree cellTree = (CellTree) tree;
TreeNode node = cellTree.getRootTreeNode();
while (!node.isChildLeaf(0)) {
node = node.setChildOpen(0, true);
}

// Top-level items are owned by the tree itself.
CellTreeNodeView<?> view = cellTree.rootNode.getChildNode(0);
assertEquals(cellTree.getElement(), getClosestRoleAncestor(view.getElement()));

// Nested items, expandable or leaf, sit in a group owned by their parent item.
while (view.getChildCount() > 0) {
view = view.getChildNode(0);
Element group = getClosestRoleAncestor(view.getElement());
assertEquals("group", group.getAttribute("role"));
assertEquals(view.getParentNode().getElement(), getClosestRoleAncestor(group));
}
assertTrue(view.isLeaf());
}

public void testExpandImagesHiddenFromAssistiveTech() {
CellTree cellTree = (CellTree) tree;
TreeNode rootNode = cellTree.getRootTreeNode();
// Reading the child count flushes the pending render of the opened node's children.
assertTrue(rootNode.setChildOpen(0, true).getChildCount() > 0);
CellTreeNodeView<?> aView = cellTree.rootNode.getChildNode(0);
assertEquals("true", aView.getImageElement().getAttribute("aria-hidden"));
CellTreeNodeView<?> aViewChild = aView.getChildNode(0);
// A leaf renders a placeholder div instead of the closed image.
assertFalse(aViewChild.isLeaf());
assertEquals("true", aViewChild.getImageElement().getAttribute("aria-hidden"));

rootNode.setChildOpen(0, false);
assertEquals("true", aView.getImageElement().getAttribute("aria-hidden"));

Element loading = Document.get().createDivElement();
loading.setInnerSafeHtml(cellTree.getLoadingImageHtml());
assertEquals("true", loading.getFirstChildElement().getAttribute("aria-hidden"));
}

private static Element getClosestRoleAncestor(Element elem) {
Element parent = elem.getParentElement();
while (parent != null && parent.getAttribute("role").isEmpty()) {
parent = parent.getParentElement();
}
return parent;
}

public void testExplicitKeyboardSelection() {
CellTree cellTree = (CellTree) tree;
TreeNode root = cellTree.getRootTreeNode();
Expand Down
Loading