summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/com/vaadin/client/ui/VUI.java36
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java179
-rw-r--r--client/src/com/vaadin/client/ui/VWindowOverlay.java77
-rw-r--r--client/src/com/vaadin/client/ui/window/WindowConnector.java7
-rw-r--r--server/src/com/vaadin/ui/Window.java109
-rw-r--r--shared/src/com/vaadin/shared/ui/window/WindowState.java13
-rw-r--r--uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html147
-rw-r--r--uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.java139
8 files changed, 702 insertions, 5 deletions
diff --git a/client/src/com/vaadin/client/ui/VUI.java b/client/src/com/vaadin/client/ui/VUI.java
index 4817bf9304..1a84613a5d 100644
--- a/client/src/com/vaadin/client/ui/VUI.java
+++ b/client/src/com/vaadin/client/ui/VUI.java
@@ -18,6 +18,7 @@ package com.vaadin.client.ui;
import java.util.ArrayList;
+import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.HasScrollHandlers;
@@ -43,6 +44,7 @@ import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.LayoutManager;
import com.vaadin.client.Profiler;
+import com.vaadin.client.Util;
import com.vaadin.client.VConsole;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
@@ -165,6 +167,8 @@ public class VUI extends SimplePanel implements ResizeHandler,
});
+ private Element storedFocus;
+
public VUI() {
super();
// Allow focusing the view by using the focus() method, the view
@@ -497,4 +501,36 @@ public class VUI extends SimplePanel implements ResizeHandler,
FocusUtil.setTabIndex(this, index);
}
+ /**
+ * Allows to store the currently focused Element.
+ *
+ * Current use case is to store the focus when a Window is opened. Does
+ * currently handle only a single value. Needs to be extended for #12158
+ *
+ * @param focusedElement
+ */
+ public void storeFocus() {
+ storedFocus = Util.getFocusedElement();
+ }
+
+ /**
+ * Restores the previously stored focus Element.
+ *
+ * Current use case is to restore the focus when a Window is closed. Does
+ * currently handle only a single value. Needs to be extended for #12158
+ *
+ * @return the lastFocusElementBeforeDialogOpened
+ */
+ public void focusStoredElement() {
+ if (storedFocus != null) {
+ storedFocus.focus();
+
+ Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+ @Override
+ public void execute() {
+ storedFocus.focus();
+ }
+ });
+ }
+ }
}
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index 1331eb106a..1756c619a7 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -20,6 +20,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import com.google.gwt.aria.client.Id;
+import com.google.gwt.aria.client.RelevantValue;
+import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style;
@@ -29,8 +32,11 @@ import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.user.client.Command;
@@ -41,22 +47,27 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorMap;
import com.vaadin.client.Focusable;
import com.vaadin.client.LayoutManager;
import com.vaadin.client.Util;
import com.vaadin.client.debug.internal.VDebugWindow;
import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
+import com.vaadin.client.ui.aria.AriaHelper;
+import com.vaadin.shared.Connector;
import com.vaadin.shared.EventId;
import com.vaadin.shared.ui.window.WindowMode;
+import com.vaadin.shared.ui.window.WindowState.WindowRole;
/**
* "Sub window" component.
*
* @author Vaadin Ltd
*/
-public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
- ScrollHandler, KeyDownHandler, FocusHandler, BlurHandler, Focusable {
+public class VWindow extends VWindowOverlay implements
+ ShortcutActionHandlerOwner, ScrollHandler, KeyDownHandler,
+ KeyUpHandler, FocusHandler, BlurHandler, Focusable {
private static ArrayList<VWindow> windowOrder = new ArrayList<VWindow>();
@@ -138,6 +149,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
private boolean closable = true;
+ private String assistivePrefix;
+ private String assistivePostfix;
+
/**
* If centered (via UIDL), the window should stay in the centered -mode
* until a position is received from the server, or the user moves or
@@ -172,13 +186,47 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
// Different style of shadow for windows
setShadowStyle("window");
+ Roles.getDialogRole().set(getElement());
+ Roles.getDialogRole().setAriaRelevantProperty(getElement(),
+ RelevantValue.ADDITIONS);
+
constructDOM();
contentPanel.addScrollHandler(this);
contentPanel.addKeyDownHandler(this);
+ contentPanel.addKeyUpHandler(this);
contentPanel.addFocusHandler(this);
contentPanel.addBlurHandler(this);
}
+ @Override
+ protected void onAttach() {
+ super.onAttach();
+
+ /*
+ * Stores the element that has focus in the application UI when the
+ * window is opened, so it can be restored when the window closes.
+ *
+ * This is currently implemented for the case when one non-modal window
+ * can be open at the same time, and the focus is not changed while the
+ * window is open.
+ */
+ getApplicationConnection().getUIConnector().getWidget().storeFocus();
+ }
+
+ @Override
+ protected void onDetach() {
+ super.onDetach();
+
+ /*
+ * Restores the previously stored focused element.
+ *
+ * When the focus was changed outside the window while the window was
+ * open, the originally stored element is restored.
+ */
+ getApplicationConnection().getUIConnector().getWidget()
+ .focusStoredElement();
+ }
+
public void bringToFront() {
int curIndex = windowOrder.indexOf(this);
if (curIndex + 1 < windowOrder.size()) {
@@ -256,7 +304,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
maximizeRestoreBox = DOM.createDiv();
DOM.setElementProperty(maximizeRestoreBox, "className", CLASSNAME
+ "-maximizebox");
+ DOM.setElementAttribute(maximizeRestoreBox, "tabindex", "0");
DOM.setElementProperty(closeBox, "className", CLASSNAME + "-closebox");
+ DOM.setElementAttribute(closeBox, "tabindex", "0");
DOM.appendChild(footer, resizeBox);
wrapper = DOM.createDiv();
@@ -275,6 +325,19 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
setWidget(contentPanel);
+ // Make the closebox accessible for assistive devices
+ Roles.getButtonRole().set(closeBox);
+ Roles.getButtonRole().setAriaLabelProperty(closeBox, "close button");
+
+ // Make the maximizebox accessible for assistive devices
+ Roles.getButtonRole().set(maximizeRestoreBox);
+ Roles.getButtonRole().setAriaLabelProperty(maximizeRestoreBox,
+ "maximize button");
+
+ // Provide the title to assistive devices
+ AriaHelper.ensureHasId(headerText);
+ Roles.getDialogRole().setAriaLabelledbyProperty(getElement(),
+ Id.of(headerText));
}
/**
@@ -622,11 +685,64 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
if (icon != null) {
icon = client.translateVaadinUri(icon);
html = "<img src=\"" + Util.escapeAttribute(icon)
- + "\" class=\"v-icon\" />" + html;
+ + "\" class=\"v-icon\" alt=\"\" />" + html;
}
+
+ // Provide information to assistive device users that a sub window was
+ // opened
+ String prefix = "<span class='"
+ + AriaHelper.ASSISTIVE_DEVICE_ONLY_STYLE + "'>"
+ + assistivePrefix + "</span>";
+ String postfix = "<span class='"
+ + AriaHelper.ASSISTIVE_DEVICE_ONLY_STYLE + "'>"
+ + assistivePostfix + "</span>";
+
+ html = prefix + html + postfix;
DOM.setInnerHTML(headerText, html);
}
+ /**
+ * Setter for the text for assistive devices the window caption is prefixed
+ * with.
+ *
+ * @param assistivePrefix
+ * the assistivePrefix to set
+ */
+ public void setAssistivePrefix(String assistivePrefix) {
+ this.assistivePrefix = assistivePrefix;
+ }
+
+ /**
+ * Getter for the text for assistive devices the window caption is prefixed
+ * with.
+ *
+ * @return the assistivePrefix
+ */
+ public String getAssistivePrefix() {
+ return assistivePrefix;
+ }
+
+ /**
+ * Setter for the text for assistive devices the window caption is postfixed
+ * with.
+ *
+ * @param assistivePostfix
+ * the assistivePostfix to set
+ */
+ public void setAssistivePostfix(String assistivePostfix) {
+ this.assistivePostfix = assistivePostfix;
+ }
+
+ /**
+ * Getter for the text for assistive devices the window caption is postfixed
+ * with.
+ *
+ * @return the assistivePostfix
+ */
+ public String getAssistivePostfix() {
+ return assistivePostfix;
+ }
+
@Override
protected Element getContainerElement() {
// in GWT 1.5 this method is used in PopupPanel constructor
@@ -995,6 +1111,13 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
}
@Override
+ public void onKeyUp(KeyUpEvent event) {
+ if (isClosable() && event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
+ onCloseClick();
+ }
+ }
+
+ @Override
public void onBlur(BlurEvent event) {
if (client.hasEventListeners(this, EventId.BLUR)) {
client.updateVariable(id, EventId.BLUR, "", true);
@@ -1030,4 +1153,54 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
- contentPanel.getElement().getOffsetWidth();
}
+ /**
+ * Allows to specify which connectors contain the description for the
+ * window. Text contained in the widgets of the connectors will be read by
+ * assistive devices when it is opened.
+ *
+ * @param connectors
+ * with the connectors of the widgets to use as description
+ */
+ public void setAssistiveDescription(Connector[] connectors) {
+ if (connectors != null) {
+ Id[] ids = new Id[connectors.length];
+ for (int index = 0; index < connectors.length; index++) {
+ if (connectors[index] == null) {
+ throw new IllegalArgumentException(
+ "All values in parameter description need to be non-null");
+ }
+
+ Element element = ((ComponentConnector) connectors[index])
+ .getWidget().getElement();
+ AriaHelper.ensureHasId(element);
+ ids[index] = Id.of(element);
+ }
+
+ Roles.getDialogRole().setAriaDescribedbyProperty(getElement(), ids);
+ } else {
+ throw new IllegalArgumentException(
+ "Parameter description must be non-null");
+ }
+ }
+
+ /**
+ * Sets the WAI-ARIA role the window.
+ *
+ * This role defines how an assistive device handles a window. Available
+ * roles are alertdialog and dialog (@see <a
+ * href="http://www.w3.org/TR/2011/CR-wai-aria-20110118/roles">Roles
+ * Model</a>).
+ *
+ * The default role is dialog.
+ *
+ * @param role
+ * WAI-ARIA role to set for the window
+ */
+ public void setWaiAriaRole(WindowRole role) {
+ if ("alertdialog".equals(role)) {
+ Roles.getAlertdialogRole().set(getElement());
+ } else {
+ Roles.getDialogRole().set(getElement());
+ }
+ }
}
diff --git a/client/src/com/vaadin/client/ui/VWindowOverlay.java b/client/src/com/vaadin/client/ui/VWindowOverlay.java
new file mode 100644
index 0000000000..efc01cf63e
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/VWindowOverlay.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2013 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.client.ui;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.vaadin.client.ApplicationConnection;
+
+public class VWindowOverlay extends VOverlay {
+ public VWindowOverlay() {
+ }
+
+ public VWindowOverlay(boolean autoHide, boolean modal, boolean showShadow) {
+ super(autoHide, modal, showShadow);
+ }
+
+ /**
+ * Gets the 'overlay container' element. Tries to find the current
+ * {@link ApplicationConnection} using {@link #getApplicationConnection()}.
+ *
+ * @return the overlay container element for the current
+ * {@link ApplicationConnection} or another element if the current
+ * {@link ApplicationConnection} cannot be determined.
+ */
+ @Override
+ public Element getOverlayContainer() {
+ ApplicationConnection ac = getApplicationConnection();
+ if (ac == null) {
+ return super.getOverlayContainer();
+ } else {
+ Element overlayContainer = getOverlayContainer(ac);
+ return overlayContainer;
+ }
+ }
+
+ /**
+ * Gets the 'overlay container' element pertaining to the given
+ * {@link ApplicationConnection}. Each overlay should be created in a
+ * overlay container element, so that the correct theme and styles can be
+ * applied.
+ *
+ * @param ac
+ * A reference to {@link ApplicationConnection}
+ * @return The overlay container
+ */
+ public static Element getOverlayContainer(ApplicationConnection ac) {
+ String id = ac.getConfiguration().getRootPanelId();
+ id = id += "-window-overlays";
+ Element container = DOM.getElementById(id);
+ if (container == null) {
+ container = DOM.createDiv();
+ container.setId(id);
+ String styles = ac.getUIConnector().getWidget().getParent()
+ .getStyleName();
+ container.addClassName(styles);
+ container.addClassName(CLASSNAME_CONTAINER);
+ RootPanel.get().getElement().appendChild(container);
+ }
+
+ return container;
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java
index 4b839384a2..ea1073dd18 100644
--- a/client/src/com/vaadin/client/ui/window/WindowConnector.java
+++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java
@@ -295,8 +295,15 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector
if (getIcon() != null) {
iconURL = getIcon();
}
+
+ window.setAssistivePrefix(state.assistivePrefix);
+ window.setAssistivePostfix(state.assistivePostfix);
window.setCaption(state.caption, iconURL);
+ window.setWaiAriaRole(getState().role);
+
+ window.setAssistiveDescription(state.contentDescription);
+
clickEventHandler.handleEventHandlerRegistration();
window.immediate = state.immediate;
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index 5820161c1c..980e96c384 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -33,10 +33,12 @@ import com.vaadin.event.ShortcutAction.ModifierKey;
import com.vaadin.event.ShortcutListener;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
+import com.vaadin.shared.Connector;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.window.WindowMode;
import com.vaadin.shared.ui.window.WindowServerRpc;
import com.vaadin.shared.ui.window.WindowState;
+import com.vaadin.shared.ui.window.WindowState.WindowRole;
import com.vaadin.util.ReflectTools;
/**
@@ -228,8 +230,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
// Don't do anything if not attached to a UI
if (uI != null) {
- // focus is restored to the parent window
- uI.focus();
// window is removed from the UI
uI.removeWindow(this);
}
@@ -995,4 +995,109 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
protected WindowState getState(boolean markAsDirty) {
return (WindowState) super.getState(markAsDirty);
}
+
+ /**
+ * Allows to specify which component contains the description for the
+ * window. Text contained in this component will be read by assistive
+ * devices when it is opened.
+ *
+ * @param connector
+ * with the component to use as description
+ */
+ public void setAssistiveDescription(Connector connector) {
+ setAssistiveDescription(new Connector[] { connector });
+ }
+
+ /**
+ * Allows to specify which components contain the description for the
+ * window. Text contained in this component will be read by assistive
+ * devices when it is opened.
+ *
+ * @param connectors
+ * with the components to use as description
+ */
+ public void setAssistiveDescription(Connector... connectors) {
+ getState().contentDescription = connectors;
+ }
+
+ /**
+ * Sets the accessibility prefix for the window caption.
+ *
+ * This prefix is read to assistive device users before the window caption,
+ * but not visible on the page.
+ *
+ * @param prefix
+ * String that is placed before the window caption
+ */
+ public void setAssistivePrefix(String prefix) {
+ getState().assistivePrefix = prefix;
+ }
+
+ /**
+ * Gets the accessibility prefix for the window caption.
+ *
+ * This prefix is read to assistive device users before the window caption,
+ * but not visible on the page.
+ *
+ * @return The accessibility prefix
+ */
+ public String getAssistivePrefix() {
+ return getState().assistivePrefix;
+ }
+
+ /**
+ * Sets the accessibility postfix for the window caption.
+ *
+ * This postfix is read to assistive device users after the window caption,
+ * but not visible on the page.
+ *
+ * @param prefix
+ * String that is placed after the window caption
+ */
+ public void setAssistivePostfix(String assistivePostfix) {
+ getState().assistivePostfix = assistivePostfix;
+ }
+
+ /**
+ * Gets the accessibility postfix for the window caption.
+ *
+ * This postfix is read to assistive device users after the window caption,
+ * but not visible on the page.
+ *
+ * @return The accessibility postfix
+ */
+ public String getAssistivePostfix() {
+ return getState().assistivePostfix;
+ }
+
+ /**
+ * Sets the WAI-ARIA role the window.
+ *
+ * This role defines how an assistive device handles a window. Available
+ * roles are alertdialog and dialog (@see <a
+ * href="http://www.w3.org/TR/2011/CR-wai-aria-20110118/roles">Roles
+ * Model</a>).
+ *
+ * The default role is dialog.
+ *
+ * @param role
+ * WAI-ARIA role to set for the window
+ */
+ public void setAssistiveRole(WindowRole role) {
+ getState().role = role;
+ }
+
+ /**
+ * Gets the WAI-ARIA role the window.
+ *
+ * This role defines how an assistive device handles a window. Available
+ * roles are alertdialog and dialog (@see <a
+ * href="http://www.w3.org/TR/2011/CR-wai-aria-20110118/roles">Roles
+ * Model</a>).
+ *
+ * @return WAI-ARIA role set for the window
+ */
+ public WindowRole getAssistiveRole() {
+ return getState().role;
+ }
}
diff --git a/shared/src/com/vaadin/shared/ui/window/WindowState.java b/shared/src/com/vaadin/shared/ui/window/WindowState.java
index 5a2d2b81b0..fa430f6c9c 100644
--- a/shared/src/com/vaadin/shared/ui/window/WindowState.java
+++ b/shared/src/com/vaadin/shared/ui/window/WindowState.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.shared.ui.window;
+import com.vaadin.shared.Connector;
import com.vaadin.shared.ui.panel.PanelState;
public class WindowState extends PanelState {
@@ -22,6 +23,13 @@ public class WindowState extends PanelState {
primaryStyleName = "v-window";
}
+ /**
+ * Available WAI-ARIA roles for a window.
+ */
+ public enum WindowRole {
+ ALERTDIALOG, DIALOG
+ };
+
public boolean modal = false;
public boolean resizable = true;
public boolean resizeLazy = false;
@@ -30,4 +38,9 @@ public class WindowState extends PanelState {
public int positionX = -1;
public int positionY = -1;
public WindowMode windowMode = WindowMode.NORMAL;
+
+ public String assistivePrefix = "";
+ public String assistivePostfix = "";
+ public Connector[] contentDescription;
+ public WindowRole role = WindowRole.DIALOG;
} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html
new file mode 100644
index 0000000000..76dcbddd0f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.html
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>ExtraWindowShownWaiAria</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">ExtraWindowShownWaiAria</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.window.ExtraWindowShownWaiAria?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementPresent</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@role</td>
+ <td>dialog</td>
+</tr>
+<tr>
+ <td>storeAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]@id</td>
+ <td>headerid</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-labelledby</td>
+ <td>${headerid}</td>
+</tr>
+<tr>
+ <td>storeAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[0]@id</td>
+ <td>descriptionid</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-describedby</td>
+ <td>${descriptionid}</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[1]@role</td>
+ <td>button</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[2]@role</td>
+ <td>button</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[3]/VCheckBox[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>storeAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[0]@id</td>
+ <td>descriptionid</td>
+</tr>
+<tr>
+ <td>storeAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VLabel[1]@id</td>
+ <td>description2id</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/@aria-describedby</td>
+ <td>${descriptionid} ${description2id}</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/FocusableScrollPanel[0]/VCssLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/</td>
+ <td></td>
+</tr>
+<tr>
+ <td>type</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[4]/VTextField[0]</td>
+ <td>Important</td>
+</tr>
+<tr>
+ <td>type</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VTextField[0]</td>
+ <td> - do ASAP</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Important</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]@class</td>
+ <td>v-assistive-device-only</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>- do ASAP</td>
+</tr>
+<tr>
+ <td>assertAttribute</td>
+ <td>vaadin=runcomvaadintestscomponentswindowExtraWindowShownWaiAria::/VWindow[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]@class</td>
+ <td>v-assistive-device-only</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.java b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.java
new file mode 100644
index 0000000000..b7c929120d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/window/ExtraWindowShownWaiAria.java
@@ -0,0 +1,139 @@
+package com.vaadin.tests.components.window;
+
+import com.vaadin.server.ThemeResource;
+import com.vaadin.shared.ui.window.WindowState.WindowRole;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.Window;
+
+public class ExtraWindowShownWaiAria extends TestBase {
+
+ @Override
+ protected void setup() {
+ final CheckBox modal = new CheckBox("Modal dialog");
+ final CheckBox additionalDescription = new CheckBox(
+ "Additional Description");
+ final TextField prefix = new TextField("Prefix: ");
+ final TextField postfix = new TextField("Postfix: ");
+
+ Button simple = new Button("Open Alert Dialog",
+ new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ CssLayout layout = new CssLayout();
+
+ final Window w = new Window("Sub window", layout);
+ w.center();
+ w.setModal(modal.getValue());
+ w.setAssistiveRole(WindowRole.ALERTDIALOG);
+ w.setAssistivePrefix(prefix.getValue());
+ w.setAssistivePostfix(postfix.getValue());
+
+ Label description1 = new Label("Simple alert dialog.");
+ layout.addComponent(description1);
+
+ if (!additionalDescription.getValue()) {
+ w.setAssistiveDescription(description1);
+ } else {
+ Label description2 = new Label(
+ "Please select what to do!");
+ layout.addComponent(description2);
+
+ w.setAssistiveDescription(description1,
+ description2);
+ }
+
+ layout.addComponent(new Button("Close",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ w.close();
+ }
+ }));
+ Button iconButton = new Button("A button with icon");
+ iconButton.setIcon(new ThemeResource(
+ "../runo/icons/16/ok.png"));
+ layout.addComponent(iconButton);
+
+ event.getButton().getUI().addWindow(w);
+ iconButton.focus();
+ }
+
+ });
+ getLayout().addComponent(simple);
+
+ Button complex = new Button("Open Entry Dialog",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ FormLayout form = new FormLayout();
+
+ final Window w = new Window("Form Window", form);
+ w.center();
+ w.setModal(modal.getValue());
+ w.setAssistivePrefix(prefix.getValue());
+ w.setAssistivePostfix(postfix.getValue());
+
+ Label description1 = new Label(
+ "Please fill in your data");
+ form.addComponent(description1);
+
+ if (!additionalDescription.getValue()) {
+ w.setAssistiveDescription(description1);
+ } else {
+ Label description2 = new Label(
+ "and press the button save.");
+ form.addComponent(description2);
+
+ w.setAssistiveDescription(description1,
+ description2);
+ }
+
+ TextField name = new TextField("Name:");
+ form.addComponent(name);
+
+ form.addComponent(new TextField("Address"));
+
+ Button saveButton = new Button("Save",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ w.close();
+ }
+ });
+ form.addComponent(saveButton);
+
+ event.getButton().getUI().addWindow(w);
+ name.focus();
+ }
+ });
+ getLayout().addComponent(complex);
+
+ getLayout().addComponent(modal);
+ getLayout().addComponent(additionalDescription);
+
+ getLayout().addComponent(prefix);
+ getLayout().addComponent(postfix);
+
+ }
+
+ @Override
+ protected String getDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}