]> source.dussan.org Git - vaadin-framework.git/commitdiff
Ensure server side focus is applied when opening a window (#17731)
authorArtur Signell <artur@vaadin.com>
Wed, 15 Jul 2015 17:37:20 +0000 (20:37 +0300)
committerMika Murtojarvi <mika@vaadin.com>
Tue, 4 Aug 2015 11:14:24 +0000 (14:14 +0300)
This change removes all deferred commands for handling window focus to
ensure
the focus events are triggered in the expected order

Change-Id: I46598243d1022b82cf64f0e60169f52248c3cc72

client/src/com/vaadin/client/ui/VUI.java
client/src/com/vaadin/client/ui/VWindow.java
uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java

index 0c1b83ab0fb63dd260947601ce463829ae7cef7b..963d83a6e615181b03709d1bc679a14d415d0728 100644 (file)
@@ -18,7 +18,6 @@ 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;
@@ -44,8 +43,8 @@ import com.vaadin.client.ConnectorMap;
 import com.vaadin.client.Focusable;
 import com.vaadin.client.LayoutManager;
 import com.vaadin.client.Profiler;
-import com.vaadin.client.WidgetUtil;
 import com.vaadin.client.VConsole;
+import com.vaadin.client.WidgetUtil;
 import com.vaadin.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
 import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
 import com.vaadin.client.ui.ui.UIConnector;
@@ -515,13 +514,6 @@ public class VUI extends SimplePanel implements ResizeHandler,
     public void focusStoredElement() {
         if (storedFocus != null) {
             storedFocus.focus();
-
-            Scheduler.get().scheduleDeferred(new ScheduledCommand() {
-                @Override
-                public void execute() {
-                    storedFocus.focus();
-                }
-            });
         }
     }
 
index e5e09f9f09487abaf553b576d9e03423f01dfa3e..e34e12a20b18b9767e31ef3a8ea25398af6c15b4 100644 (file)
@@ -562,17 +562,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
     }
 
     private static void focusTopmostModalWindow() {
-        // If we call focus() directly without scheduling, it does not work in
-        // IE and FF.
-        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
-            @Override
-            public void execute() {
-                VWindow topmost = getTopmostWindow();
-                if ((topmost != null) && (topmost.vaadinModality)) {
-                    topmost.focus();
-                }
-            }
-        });
+        VWindow topmost = getTopmostWindow();
+        if ((topmost != null) && (topmost.vaadinModality)) {
+            topmost.focus();
+        }
     }
 
     @Override
@@ -1373,7 +1366,11 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
 
     @Override
     public void focus() {
-        contentPanel.focus();
+        // We don't want to use contentPanel.focus() as that will use a timer in
+        // Chrome/Safari and ultimately run focus events in the wrong order when
+        // opening a modal window and focusing some other component at the same
+        // time
+        contentPanel.getElement().focus();
     }
 
     private int getDecorationHeight() {
diff --git a/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusField.java
new file mode 100644 (file)
index 0000000..1c82a3d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 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.window;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.Window;
+
+public class OpenModalWindowAndFocusField extends AbstractTestUIWithLog {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        Button button = new Button("Open modal and focus textarea");
+        button.setId("openFocus");
+        button.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                open(true);
+            }
+        });
+        addComponent(button);
+
+        button = new Button("Only open modal");
+        button.setId("open");
+        button.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                open(false);
+            }
+
+        });
+        addComponent(button);
+
+    }
+
+    private void open(boolean focus) {
+        Window wind = new Window();
+        wind.setModal(true);
+        TextArea ta = new TextArea();
+        wind.setContent(ta);
+        addWindow(wind);
+        if (focus) {
+            ta.focus();
+        }
+    }
+}
diff --git a/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java b/uitest/src/com/vaadin/tests/components/window/OpenModalWindowAndFocusFieldTest.java
new file mode 100644 (file)
index 0000000..5dba1c3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2000-2014 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.window;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TextAreaElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class OpenModalWindowAndFocusFieldTest extends MultiBrowserTest {
+
+    @Test
+    public void openModalAndFocusField() {
+        openTestURL();
+        $(ButtonElement.class).id("openFocus").click();
+        TextAreaElement textArea = $(TextAreaElement.class).first();
+
+        assertElementsEquals(textArea, getActiveElement());
+    }
+
+    @Test
+    public void openModal() {
+        openTestURL();
+        $(ButtonElement.class).id("open").click();
+        // WindowElement window = $(WindowElement.class).first();
+        WebElement windowFocusElement = findElement(By
+                .xpath("//div[@class='v-window-contents']/div[@class='v-scrollable']"));
+
+        assertElementsEquals(windowFocusElement, getActiveElement());
+    }
+
+}
index 0e983ab95994e9458a95a1737434f28395c25210..2e3854cb2bc4648ddb8c527633d2fb8385c963a6 100644 (file)
@@ -50,6 +50,7 @@ import org.openqa.selenium.interactions.Keyboard;
 import org.openqa.selenium.interactions.Mouse;
 import org.openqa.selenium.interactions.internal.Coordinates;
 import org.openqa.selenium.internal.Locatable;
+import org.openqa.selenium.internal.WrapsElement;
 import org.openqa.selenium.remote.DesiredCapabilities;
 import org.openqa.selenium.remote.HttpCommandExecutor;
 import org.openqa.selenium.remote.RemoteWebDriver;
@@ -1176,4 +1177,22 @@ public abstract class AbstractTB3Test extends ParallelTest {
 
         return ((Number) executeScript(script, e)).intValue();
     }
+
+    protected void assertElementsEquals(WebElement expectedElement,
+            WebElement actualElement) {
+        while (expectedElement instanceof WrapsElement) {
+            expectedElement = ((WrapsElement) expectedElement)
+                    .getWrappedElement();
+        }
+        while (actualElement instanceof WrapsElement) {
+            actualElement = ((WrapsElement) actualElement).getWrappedElement();
+        }
+
+        Assert.assertEquals(expectedElement, actualElement);
+    }
+
+    protected WebElement getActiveElement() {
+        return (WebElement) executeScript("return document.activeElement;");
+
+    }
 }