]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add aria-rowcount to grid (#10167)
authorKnoobie <Knoobie@gmx.de>
Wed, 11 Oct 2017 10:15:26 +0000 (12:15 +0200)
committerHenri Sara <henri.sara@gmail.com>
Wed, 11 Oct 2017 10:15:26 +0000 (13:15 +0300)
This is based on discussion from vaadin/vaadin-grid#1023 .

client/src/main/java/com/vaadin/client/widgets/Escalator.java
uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaMultiselectable.java
uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaRowcount.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcount.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaRowcountTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcountTest.java [new file with mode: 0644]

index cd5464a1cc3f272a103b6b15f2bab1a1bab243f2..6adc0cbef93670112648567c9957a347f2fb8399 100644 (file)
@@ -1124,6 +1124,73 @@ public class Escalator extends Widget
         }
     }
 
+    /**
+     * Helper class that helps to implement the WAI-ARIA functionality
+     * for the Grid and TreeGrid component.
+     * <p>
+     * The following WAI-ARIA attributes are added through this class:
+     *
+     * <ul>
+     *     <li>aria-rowcount (since 8.2)</li>
+     * </ul>
+     *
+     * @since 8.2
+     */
+    public class AriaGridHelper {
+
+        /**
+         * This field contains the total number of rows from the grid
+         * including rows from thead, tbody and tfoot.
+         *
+         * @since 8.2
+         */
+        private int allRows;
+
+        /**
+         * Adds the given numberOfRows to allRows and calls
+         * {@link #updateAriaRowCount()}.
+         *
+         * @param numberOfRows number of rows that were added to the
+         *                     grid
+         *
+         * @since 8.2
+         */
+        public void addRows(int numberOfRows) {
+            allRows += numberOfRows;
+            updateAriaRowCount();
+        }
+
+        /**
+         * Removes the given numberOfRows from allRows and calls
+         * {@link #updateAriaRowCount()}.
+         *
+         * @param numberOfRows number of rows that were removed from
+         *                     the grid
+         *
+         * @since 8.2
+         */
+        public void removeRows(int numberOfRows) {
+            allRows -= numberOfRows;
+            updateAriaRowCount();
+        }
+
+        /**
+         * Sets the aria-rowcount attribute with the current value
+         * of {@link AriaGridHelper#allRows} if the grid is attached
+         * and {@link AriaGridHelper#allRows} > 0.
+         *
+         * @since 8.2
+         */
+        public void updateAriaRowCount() {
+            if (!isAttached() || 0 > allRows) {
+
+                return;
+            }
+
+            getTable().setAttribute("aria-rowcount", String.valueOf(allRows));
+        }
+    }
+
     public abstract class AbstractRowContainer implements RowContainer {
         private EscalatorUpdater updater = EscalatorUpdater.NULL;
 
@@ -1150,8 +1217,7 @@ public class Escalator extends Widget
 
         private boolean initialColumnSizesCalculated = false;
 
-        public AbstractRowContainer(
-                final TableSectionElement rowContainerElement) {
+        public AbstractRowContainer(final TableSectionElement rowContainerElement) {
             root = rowContainerElement;
         }
 
@@ -1216,6 +1282,7 @@ public class Escalator extends Widget
             assertArgumentsAreValidAndWithinRange(index, numberOfRows);
 
             rows -= numberOfRows;
+            ariaGridHelper.removeRows(numberOfRows);
 
             if (!isAttached()) {
                 return;
@@ -1340,6 +1407,7 @@ public class Escalator extends Widget
             }
 
             rows += numberOfRows;
+            ariaGridHelper.addRows(numberOfRows);
             /*
              * only add items in the DOM if the widget itself is attached to the
              * DOM. We can't calculate sizes otherwise.
@@ -2168,8 +2236,7 @@ public class Escalator extends Widget
         /** The height of the combined rows in the DOM. Never negative. */
         private double heightOfSection = 0;
 
-        public AbstractStaticRowContainer(
-                final TableSectionElement headElement) {
+        public AbstractStaticRowContainer(final TableSectionElement headElement) {
             super(headElement);
         }
 
@@ -5594,9 +5661,10 @@ public class Escalator extends Widget
     private final VerticalScrollbarBundle verticalScrollbar = new VerticalScrollbarBundle();
     private final HorizontalScrollbarBundle horizontalScrollbar = new HorizontalScrollbarBundle();
 
+    private final AriaGridHelper ariaGridHelper = new AriaGridHelper();
+
     private final HeaderRowContainer header = new HeaderRowContainer(headElem);
-    private final BodyRowContainerImpl body = new BodyRowContainerImpl(
-            bodyElem);
+    private final BodyRowContainerImpl body = new BodyRowContainerImpl(bodyElem);
     private final FooterRowContainer footer = new FooterRowContainer(footElem);
 
     /**
@@ -5608,6 +5676,7 @@ public class Escalator extends Widget
 
     private final ColumnConfigurationImpl columnConfiguration = new ColumnConfigurationImpl();
     private final DivElement tableWrapper;
+    private final Element table;
 
     private final DivElement horizontalScrollbarDeco = DivElement
             .as(DOM.createDiv());
@@ -5662,7 +5731,7 @@ public class Escalator extends Widget
 
         root.appendChild(tableWrapper);
 
-        final Element table = DOM.createTable();
+        table = DOM.createTable();
         tableWrapper.appendChild(table);
 
         table.appendChild(headElem);
@@ -6799,7 +6868,7 @@ public class Escalator extends Widget
      * @since 8.2
      */
     public Element getTable() {
-        return getTableWrapper().getFirstChildElement();
+        return table;
     }
 
     private Element getSubPartElementTableStructure(SubPartArguments args) {
index 144e518c439e2df3fa4f8e7dc1d2ceb942652b8a..0841c5f3b1573d617db3b93157aa56724ca0dfdd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2016 Vaadin Ltd.
+ * Copyright 2000-2017 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
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaRowcount.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridAriaRowcount.java
new file mode 100644 (file)
index 0000000..2f67a63
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2017 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 GridAriaRowcount extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        Grid<String> grid = new Grid<>();
+        grid.addColumn(ValueProvider.identity());
+        grid.setItems("a", "b");
+        addComponent(grid);
+
+        addComponent(new Button("addFooter", event -> grid.addFooterRowAt(0)));
+        addComponent(new Button("removeFooter", event -> grid.removeFooterRow(0)));
+
+        addComponent(new Button("addHeader", event -> grid.addHeaderRowAt(1)));
+        addComponent(new Button("removeHeader", event -> grid.removeHeaderRow(1)));
+
+        addComponent(new Button("setItemsTo3", event -> grid.setItems("a", "b", "c")));
+        addComponent(new Button("setItemsTo6", event -> grid.setItems("a", "b", "c", "d", "e", "f")));
+
+        addComponent(new Button("updateAll", event -> {
+            grid.addFooterRowAt(0);
+            grid.addHeaderRowAt(0);
+            grid.setItems("a", "b", "c", "d");
+        }));
+
+    }
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcount.java b/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcount.java
new file mode 100644 (file)
index 0000000..ed0a892
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2017 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.treegrid;
+
+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.TreeGrid;
+
+/**
+ * @author Vaadin Ltd
+ *
+ */
+public class TreeGridAriaRowcount extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        TreeGrid<String> grid = new TreeGrid<>();
+        grid.addColumn(ValueProvider.identity());
+        grid.setItems("a", "b");
+        addComponent(grid);
+
+        addComponent(new Button("addFooter", event -> grid.addFooterRowAt(0)));
+        addComponent(new Button("removeFooter", event -> grid.removeFooterRow(0)));
+
+        addComponent(new Button("addHeader", event -> grid.addHeaderRowAt(1)));
+        addComponent(new Button("removeHeader", event -> grid.removeHeaderRow(1)));
+
+        addComponent(new Button("setItemsTo3", event -> grid.setItems("a", "b", "c")));
+        addComponent(new Button("setItemsTo6", event -> grid.setItems("a", "b", "c", "d", "e", "f")));
+
+        addComponent(new Button("updateAll", event -> {
+            grid.addFooterRowAt(0);
+            grid.addHeaderRowAt(0);
+            grid.setItems("a", "b", "c", "d");
+        }));
+
+    }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaRowcountTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridAriaRowcountTest.java
new file mode 100644 (file)
index 0000000..cf2bdeb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2000-2017 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;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vaadin Ltd
+ */
+public class GridAriaRowcountTest extends SingleBrowserTest {
+
+    private GridElement grid;
+
+    @Test
+    public void checkGridAriaRowcount() {
+        openTestURL();
+
+        grid = $(GridElement.class).first();
+
+        // default with 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("addFooter").first().click();
+        // 1 header row, 2 body rows and 1 footer row.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("removeFooter").first().click();
+        // 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("addHeader").first().click();
+        // 2 header row and 2 body rows.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("removeHeader").first().click();
+        // 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("setItemsTo3").first().click();
+        // 1 header row and 3 body rows.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("setItemsTo6").first().click();
+        // 1 header row and 6 body rows.
+        assertTrue("Grid should have 7 rows", containsRows(7));
+
+        $(ButtonElement.class).caption("updateAll").first().click();
+        // 2 header rows, 4 body rows and 1 footer row.
+        assertTrue("Grid should have 7 rows", containsRows(7));
+    }
+
+    private boolean containsRows(int rowcount) {
+        return grid.getHTML().contains("aria-rowcount=\"" + String.valueOf(rowcount) + "\"");
+    }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcountTest.java b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridAriaRowcountTest.java
new file mode 100644 (file)
index 0000000..df940c7
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2017 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.treegrid;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TreeGridElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vaadin Ltd
+ */
+public class TreeGridAriaRowcountTest extends SingleBrowserTest {
+
+    private TreeGridElement grid;
+
+    @Test
+    public void checkTreeGridAriaRowcount() {
+        openTestURL();
+
+        grid = $(TreeGridElement.class).first();
+
+        // default with 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("addFooter").first().click();
+        // 1 header row, 2 body rows and 1 footer row.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("removeFooter").first().click();
+        // 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("addHeader").first().click();
+        // 2 header row and 2 body rows.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("removeHeader").first().click();
+        // 1 header row and 2 body rows.
+        assertTrue("Grid should have 3 rows", containsRows(3));
+
+        $(ButtonElement.class).caption("setItemsTo3").first().click();
+        // 1 header row and 3 body rows.
+        assertTrue("Grid should have 4 rows", containsRows(4));
+
+        $(ButtonElement.class).caption("setItemsTo6").first().click();
+        // 1 header row and 6 body rows.
+        assertTrue("Grid should have 7 rows", containsRows(7));
+
+        $(ButtonElement.class).caption("updateAll").first().click();
+        // 2 header rows, 4 body rows and 1 footer row.
+        assertTrue("Grid should have 7 rows", containsRows(7));
+    }
+
+    private boolean containsRows(int rowcount) {
+        return grid.getHTML().contains("aria-rowcount=\"" + String.valueOf(rowcount) + "\"");
+    }
+}