From 80336d30ed12d53f24c01de5c4b6274ccc094b3b Mon Sep 17 00:00:00 2001 From: Knoobie Date: Wed, 4 Oct 2017 07:51:31 +0200 Subject: [PATCH] Add role="grid" and aria-multiselectable to grid (#10009) Also adds aria-selected for grid rows. --- all/src/main/templates/release-notes.html | 1 + .../grid/MultiSelectionModelConnector.java | 4 ++ .../grid/SingleSelectionModelConnector.java | 5 ++ .../widget/grid/selection/SelectionModel.java | 15 ++++++ .../client/widget/treegrid/TreeGrid.java | 7 +++ .../com/vaadin/client/widgets/Escalator.java | 10 ++++ .../java/com/vaadin/client/widgets/Grid.java | 30 +++++++++-- .../grid/GridAriaMultiselectable.java | 50 +++++++++++++++++++ .../grid/GridAriaMultiselectableTest.java | 50 +++++++++++++++++++ 9 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaMultiselectable.java create mode 100644 uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaMultiselectableTest.java diff --git a/all/src/main/templates/release-notes.html b/all/src/main/templates/release-notes.html index 8db3ef8670..be04a7247a 100644 --- a/all/src/main/templates/release-notes.html +++ b/all/src/main/templates/release-notes.html @@ -120,6 +120,7 @@
  • Error indicators are now <span class="v-errorindicator"></span> elements.
  • Embedded is not a LegacyComponent anymore.
  • Notification method show returns Notification, instead of void.
  • +
  • The client side SelectionModel interface has a new method isMultiSelectionAllowed.
  • For incompatible or behavior-altering changes in 8.1, please see 8.1 release notes

    diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java index 92b858cb97..79a3cac92b 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/MultiSelectionModelConnector.java @@ -121,6 +121,10 @@ public class MultiSelectionModelConnector return isSelectionAllowed; } + @Override + public boolean isMultiSelectionAllowed() { + return true; + } } @Override diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java index 560ccb2d85..2320edc8e0 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/SingleSelectionModelConnector.java @@ -82,6 +82,11 @@ public class SingleSelectionModelConnector return isSelectionAllowed; } + @Override + public boolean isMultiSelectionAllowed() { + return false; + } + /** * Sets whether it's allowed to deselect the selected row through the * UI. Deselection is allowed by default. diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModel.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModel.java index 17763b0a94..513ee4949a 100644 --- a/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModel.java +++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/SelectionModel.java @@ -58,6 +58,11 @@ public interface SelectionModel { public boolean isSelectionAllowed() { return false; } + + @Override + public boolean isMultiSelectionAllowed() { + return false; + } } /** @@ -115,6 +120,16 @@ public interface SelectionModel { */ boolean isSelectionAllowed(); + /** + * Checks if the user is allowed to have more than on item selected. + *

    + * + * @return true if the user is allowed to select multiple items, + * false otherwise + * @since 8.2 + */ + boolean isMultiSelectionAllowed(); + /** * Gets the selected state from a given grid row json object. This is a * helper method for grid selection models. diff --git a/client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java b/client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java index 016c701deb..cf9d7ea833 100644 --- a/client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java +++ b/client/src/main/java/com/vaadin/client/widget/treegrid/TreeGrid.java @@ -44,6 +44,13 @@ public class TreeGrid extends Grid { */ private String depthStyleNamePrefix; + /** + * Creates a new instance. + */ + public TreeGrid() { + setAriaRole("treegrid"); + } + /** * Body updater that adds additional style to each row containing depth * information inside the hierarchy. diff --git a/client/src/main/java/com/vaadin/client/widgets/Escalator.java b/client/src/main/java/com/vaadin/client/widgets/Escalator.java index a46450fe07..640304e828 100644 --- a/client/src/main/java/com/vaadin/client/widgets/Escalator.java +++ b/client/src/main/java/com/vaadin/client/widgets/Escalator.java @@ -6792,6 +6792,16 @@ public class Escalator extends Widget return tableWrapper; } + /** + * Returns the {@code } element of the grid. + * + * @return the table element + * @since 8.2 + */ + public Element getTable() { + return getTableWrapper().getFirstChildElement(); + } + private Element getSubPartElementTableStructure(SubPartArguments args) { String type = args.getType(); diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java index e4ceac93f8..81f6756930 100755 --- a/client/src/main/java/com/vaadin/client/widgets/Grid.java +++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java @@ -5597,10 +5597,15 @@ public class Grid extends ResizeComposite implements HasSelectionHandlers, rowReference.set(rowIndex, rowData, rowElement); - if (hasData) { - setStyleName(rowElement, rowSelectedStyleName, - isSelected(rowData)); + boolean isSelected = hasData && isSelected(rowData); + if (Grid.this.selectionModel.isSelectionAllowed()) { + rowElement.setAttribute("aria-selected", String.valueOf(isSelected)); + } else { + rowElement.removeAttribute("aria-selected"); + } + if (hasData) { + setStyleName(rowElement, rowSelectedStyleName, isSelected); if (rowStyleGenerator != null) { try { String rowStylename = rowStyleGenerator @@ -6148,6 +6153,7 @@ public class Grid extends ResizeComposite implements HasSelectionHandlers, cellFocusHandler = new CellFocusHandler(); setStylePrimaryName(STYLE_NAME); + setAriaRole("grid"); escalator.getHeader().setEscalatorUpdater(createHeaderUpdater()); escalator.getBody().setEscalatorUpdater(createBodyUpdater()); @@ -6308,6 +6314,17 @@ public class Grid extends ResizeComposite implements HasSelectionHandlers, } } + /** + * Adds the given role as 'role="$param"' to the {@code
    } element + * of the grid. + * + * @param role the role param + * @since 8.2 + */ + protected void setAriaRole(String role){ + escalator.getTable().setAttribute("role", role); + } + /** * Creates the escalator updater used to update the header rows in this * grid. The updater is invoked when header rows or columns are added or @@ -7971,6 +7988,13 @@ public class Grid extends ResizeComposite implements HasSelectionHandlers, setSelectColumnRenderer(null); } + if (this.selectionModel.isMultiSelectionAllowed()) { + escalator.getTable().setAttribute("aria-multiselectable", "true"); + } else if (this.selectionModel.isSelectionAllowed()) { + escalator.getTable().setAttribute("aria-multiselectable", "false"); + } else { + escalator.getTable().removeAttribute("aria-multiselectable"); + } // Refresh rendered rows to update selection, if it has changed requestRefreshBody(); } diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaMultiselectable.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaMultiselectable.java new file mode 100644 index 0000000000..144e518c43 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaMultiselectable.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import com.vaadin.data.ValueProvider; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.SelectionMode; + +/** + * @author Vaadin Ltd + * + */ +public class GridAriaMultiselectable extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Grid grid = new Grid<>(); + grid.addColumn(ValueProvider.identity()); + grid.setItems("a", "b"); + grid.setSelectionMode(SelectionMode.NONE); + + addComponent(grid); + + Button singleSelectBtn = new Button("SingleSelect", event -> { + grid.setSelectionMode(SelectionMode.SINGLE); + }); + addComponent(singleSelectBtn); + + Button multiSelectBtn = new Button("MultiSelect", event -> { + grid.setSelectionMode(SelectionMode.MULTI); + }); + addComponent(multiSelectBtn); + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaMultiselectableTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaMultiselectableTest.java new file mode 100644 index 0000000000..eb6cd44f50 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaMultiselectableTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.tests.tb3.SingleBrowserTest; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Vaadin Ltd + */ +public class GridAriaMultiselectableTest extends SingleBrowserTest { + + @Test + public void checkAriaMultiselectable() { + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + + Assert.assertTrue("Grid should have the role 'grid'", + grid.getHTML().contains("role=\"grid\"")); + Assert.assertFalse("Grid should not have aria-multiselectable", + grid.getHTML().contains("aria-multiselectable")); + + $(ButtonElement.class).caption("SingleSelect").first().click(); + + Assert.assertTrue("Grid should have aria-multiselectable 'false'", + grid.getHTML().contains("aria-multiselectable=\"false\"")); + + $(ButtonElement.class).caption("MultiSelect").first().click(); + + Assert.assertTrue("Grid should have aria-multiselectable 'true'", + grid.getHTML().contains("aria-multiselectable=\"true\"")); + } +} -- 2.39.5