aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Török <31210544+torok-peter@users.noreply.github.com>2017-11-07 11:39:11 +0200
committerGitHub <noreply@github.com>2017-11-07 11:39:11 +0200
commitb5b57375a3b785d758e09a4f27d3023b87e6f339 (patch)
treedf9652d6e979534a5018ca63f011a0519e73ac44
parentf7abbea6bef3eb46fa4f3580a7da2a2440463266 (diff)
downloadvaadin-framework-b5b57375a3b785d758e09a4f27d3023b87e6f339.tar.gz
vaadin-framework-b5b57375a3b785d758e09a4f27d3023b87e6f339.zip
Make focus circulate in modal dialog to improve accessibility (#10260)
Make focus circulate in modal dialog to improve accessibility
-rw-r--r--client/src/main/java/com/vaadin/client/ui/FocusUtil.java23
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VWindow.java10
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpened.java8
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/window/ModalWindowFocus.java2
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpenedTest.java8
5 files changed, 47 insertions, 4 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/FocusUtil.java b/client/src/main/java/com/vaadin/client/ui/FocusUtil.java
index 16b3f68456..9a0a4ecea4 100644
--- a/client/src/main/java/com/vaadin/client/ui/FocusUtil.java
+++ b/client/src/main/java/com/vaadin/client/ui/FocusUtil.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.client.ui;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.Widget;
@@ -94,4 +95,26 @@ public class FocusUtil {
return focusable.getElement().getTabIndex();
}
+
+ public static native Element[] getFocusableChildren(Element parent)
+ /*-{
+ var focusableChildren = parent.querySelectorAll('[type][tabindex]:not([tabindex="-1"]), [role=button][tabindex]:not([tabindex="-1"])');
+ return focusableChildren;
+ }-*/;
+
+ public static void focusOnFirstFocusableElement(Element parent)
+ {
+ Element[] focusableChildren = getFocusableChildren(parent);
+ if (focusableChildren.length > 0) {
+ focusableChildren[0].focus();
+ }
+ }
+
+ public static void focusOnLastFocusableElement(Element parent)
+ {
+ Element[] focusableChildren = getFocusableChildren(parent);
+ if (focusableChildren.length > 0) {
+ focusableChildren[focusableChildren.length - 1].focus();
+ }
+ }
}
diff --git a/client/src/main/java/com/vaadin/client/ui/VWindow.java b/client/src/main/java/com/vaadin/client/ui/VWindow.java
index e7618ed59b..e53997ec17 100644
--- a/client/src/main/java/com/vaadin/client/ui/VWindow.java
+++ b/client/src/main/java/com/vaadin/client/ui/VWindow.java
@@ -429,14 +429,18 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
Roles.getDialogRole().setAriaLabelledbyProperty(getElement(),
Id.of(headerText));
- // Handlers to Prevent tab to leave the window
+ // Handlers to Prevent tab to leave the window (by circulating focus)
// and backspace to cause browser navigation
topEventBlocker = event -> {
+ if (!getElement().isOrHasChild(WidgetUtil.getFocusedElement())) {
+ return;
+ }
NativeEvent nativeEvent = event.getNativeEvent();
if (nativeEvent.getEventTarget().cast() == topTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_TAB
&& nativeEvent.getShiftKey()) {
nativeEvent.preventDefault();
+ FocusUtil.focusOnLastFocusableElement(this.getElement());
}
if (nativeEvent.getEventTarget().cast() == topTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_BACKSPACE) {
@@ -445,11 +449,15 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
};
bottomEventBlocker = event -> {
+ if (!getElement().isOrHasChild(WidgetUtil.getFocusedElement())) {
+ return;
+ }
NativeEvent nativeEvent = event.getNativeEvent();
if (nativeEvent.getEventTarget().cast() == bottomTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_TAB
&& !nativeEvent.getShiftKey()) {
nativeEvent.preventDefault();
+ FocusUtil.focusOnFirstFocusableElement(this.getElement());
}
if (nativeEvent.getEventTarget().cast() == bottomTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_BACKSPACE) {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpened.java b/uitest/src/main/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpened.java
index 2aca0b91f2..5cc3c02016 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpened.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpened.java
@@ -15,11 +15,13 @@
*/
package com.vaadin.tests.components.window;
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.VaadinRequest;
-import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
@@ -27,7 +29,9 @@ import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
-public class BackspaceKeyWithModalOpened extends AbstractReindeerTestUI {
+@Theme("valo")
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public class BackspaceKeyWithModalOpened extends AbstractTestUI {
private static final String DEFAULT_VIEW_ID = "";
private static final String SECOND_VIEW_ID = "second";
diff --git a/uitest/src/main/java/com/vaadin/tests/components/window/ModalWindowFocus.java b/uitest/src/main/java/com/vaadin/tests/components/window/ModalWindowFocus.java
index a9578840d2..9e77600213 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/window/ModalWindowFocus.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/window/ModalWindowFocus.java
@@ -15,12 +15,14 @@
*/
package com.vaadin.tests.components.window;
+import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractReindeerTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Window;
+@Widgetset("com.vaadin.DefaultWidgetSet")
public class ModalWindowFocus extends AbstractReindeerTestUI {
@Override
diff --git a/uitest/src/test/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpenedTest.java b/uitest/src/test/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpenedTest.java
index ce015bab9d..b9199e0aec 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpenedTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/window/BackspaceKeyWithModalOpenedTest.java
@@ -22,6 +22,7 @@ import static org.openqa.selenium.Keys.BACK_SPACE;
import static org.openqa.selenium.Keys.TAB;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
@@ -60,9 +61,14 @@ public class BackspaceKeyWithModalOpenedTest extends MultiBrowserTest {
}
/**
- * Tests that backspace action in the bottom component is prevented
+ * Tests that backspace action in the bottom component is prevented.
+ *
+ * Ignored because the fix to #8855 stops the top and bottom components
+ * from functioning as focus traps. Meanwhile, navigation with Backspace
+ * is not anymore supported by reasonable browsers.
*/
@Test
+ @Ignore
public void testWithFocusOnBottom() throws Exception {
TextFieldElement textField = getTextField();