diff options
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; + } + +} |