aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Tuikkala <johannes@vaadin.com>2015-03-05 13:32:33 +0200
committerLeif Åstrand <leif@vaadin.com>2015-03-26 16:16:52 +0200
commit7f253a23f696f1cdee2abae1b7558993eea65915 (patch)
tree33f10bc68a72fb18b3cdaed0d2c8baca3dc461a6
parentcb53601d9bc9be366635df51a8f9af3e92d3c5c7 (diff)
downloadvaadin-framework-7f253a23f696f1cdee2abae1b7558993eea65915.tar.gz
vaadin-framework-7f253a23f696f1cdee2abae1b7558993eea65915.zip
Fixed scroll jump by using native focusing in IE (#15294)
Change-Id: I412ba219f31567ebba019b7d6ce4db4af9be9363
-rw-r--r--WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html12
-rw-r--r--client/src/com/vaadin/client/ui/FocusableScrollPanel.java8
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java153
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java64
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java127
5 files changed, 364 insertions, 0 deletions
diff --git a/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html
new file mode 100644
index 0000000000..dfddbdb7e5
--- /dev/null
+++ b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<title>IEJumpTest</title>
+</head>
+<!-- This is for testing Vaadin UI in iFrame (test class TableInIframeRowClickScrollJumpTest, for ticket #15294 -->
+<body>
+ <div style="font-size: 4px">test div</div>
+ <iframe id="test-iframe-0" src="/run/com.vaadin.tests.components.table.TableBlurFocus" width="100%" height="2000px" style="visibility: visible;">
+ </iframe>
+</body>
+
+</html> \ No newline at end of file
diff --git a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
index 475c8f8074..9dd9c17675 100644
--- a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
+++ b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
@@ -48,9 +48,11 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
Style style = getElement().getStyle();
style.setProperty("zoom", "1");
style.setPosition(Position.RELATIVE);
+ browserInfo = BrowserInfo.get();
}
private DivElement focusElement;
+ private BrowserInfo browserInfo;
public FocusableScrollPanel(boolean useFakeFocusElement) {
this();
@@ -72,6 +74,12 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
style.setPosition(Position.FIXED);
style.setTop(0, Unit.PX);
style.setLeft(0, Unit.PX);
+ if (browserInfo.isIE()) {
+ // for #15294: artificially hide little bit more the
+ // focusElement, otherwise IE will make the window to scroll
+ // into it when focused
+ style.setLeft(-999, Unit.PX);
+ }
getElement().appendChild(focusElement);
/* Sink from focusElemet too as focusa and blur don't bubble */
DOM.sinkEvents(focusElement, Event.FOCUSEVENTS);
diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java
new file mode 100644
index 0000000000..d95b406c1a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java
@@ -0,0 +1,153 @@
+/*
+ * 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.table;
+
+import java.util.Map;
+
+import com.vaadin.event.FieldEvents.BlurEvent;
+import com.vaadin.event.FieldEvents.BlurListener;
+import com.vaadin.event.FieldEvents.FocusEvent;
+import com.vaadin.event.FieldEvents.FocusListener;
+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.Button.ClickListener;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Table;
+
+/**
+ * Tests that previously focused component's blur event happens before any
+ * variable changes in the focused Table.
+ *
+ * @author Vaadin Ltd
+ */
+public class TableBlurFocus extends AbstractTestUIWithLog {
+
+ enum Columns {
+ COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN5
+ }
+
+ private int count = 0;
+ private Button focusButton;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ System.out
+ .println("TableBlurFocus/TableInIframeRowClickScrollJumpTest");
+ Button button = new Button("click to focus");
+ button.addFocusListener(new FocusListener() {
+
+ @Override
+ public void focus(FocusEvent event) {
+ log("focus");
+ }
+ });
+ button.addBlurListener(new BlurListener() {
+
+ @Override
+ public void blur(BlurEvent event) {
+ log("blur");
+ }
+ });
+ final Button scrollButton = new Button(
+ "focus lowest button to scroll down");
+ scrollButton.setId("scroll-button");
+ scrollButton.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ focusButton.focus();
+ }
+ });
+
+ Label spacerLabel = new Label("spacer");
+ spacerLabel.setHeight("300px");
+
+ addComponent(button);
+ addComponent(scrollButton);
+ addComponent(createTable());
+ addComponent(spacerLabel);
+ addComponent(focusButton = new Button("for focus"));
+ focusButton.setId("focus-button");
+ focusButton.addFocusListener(new FocusListener() {
+ @Override
+ public void focus(FocusEvent event) {
+ focusButton.setCaption("focused");
+ }
+ });
+ }
+
+ private Table createTable() {
+ Table table = new Table() {
+ @Override
+ public void changeVariables(Object source,
+ Map<String, Object> variables) {
+ log("variable change");
+ super.changeVariables(source, variables);
+ }
+ };
+ table.setSelectable(true);
+ table.setImmediate(true);
+
+ table.addContainerProperty(Columns.COLUMN1, String.class, " ");
+ table.addContainerProperty(Columns.COLUMN2, Label.class, null);
+ table.addContainerProperty(Columns.COLUMN3, Button.class, null);
+ table.addContainerProperty(Columns.COLUMN4, String.class, " ");
+ table.setColumnCollapsingAllowed(true);
+ table.setColumnCollapsible(Columns.COLUMN4, true);
+ table.setColumnCollapsed(Columns.COLUMN4, true);
+ table.setSortEnabled(true);
+ table.setFooterVisible(true);
+ table.setPageLength(14);
+ table.addGeneratedColumn(Columns.COLUMN5, new Table.ColumnGenerator() {
+
+ @Override
+ public Object generateCell(Table source, Object itemId,
+ Object columnId) {
+ return "Generated";
+ }
+ });
+
+ table.setColumnHeader(Columns.COLUMN1, "Column");
+ for (int x = 0; x < 120; x++) {
+ final Label buttonLabel = new Label("Not clicked");
+ Button button = new Button("Click me?", new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(Button.ClickEvent event) {
+ ++count;
+ buttonLabel.setValue("Clicked " + count + " times");
+ Notification.show("Clicked!");
+ }
+ });
+ table.addItem(new Object[] { "entryString" + x, buttonLabel,
+ button, " " }, "entryID" + x);
+ }
+ return table;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Click button to focus, then click Table header. Blur event should arrive before the next variable change.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 15294;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java
new file mode 100644
index 0000000000..e5d07abc22
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.table;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TableBlurFocusTest extends MultiBrowserTest {
+
+ @Test
+ public void testBlurAndFocus() throws InterruptedException {
+ openTestURL();
+ waitForElementPresent(By.className("v-button"));
+
+ assertAnyLogText("1. variable change");
+ assertEquals("Unexpected column header,", "COLUMN2",
+ $(TableElement.class).first().getHeaderCell(1).getCaption());
+ assertEquals("Unexpected button caption,", "click to focus",
+ $(ButtonElement.class).first().getCaption());
+
+ $(ButtonElement.class).first().click();
+ assertAnyLogText("2. focus", "3. focus");
+
+ $(TableElement.class).first().getHeaderCell(1).click();
+ assertAnyLogText("3. blur", "4. blur");
+ }
+
+ private void assertAnyLogText(String... texts) {
+ assertThat(String.format(
+ "Correct log text was not found, expected any of %s",
+ Arrays.asList(texts)), logContainsAnyText(texts));
+ }
+
+ private boolean logContainsAnyText(String... texts) {
+ for (String text : texts) {
+ if (logContainsText(text)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java
new file mode 100644
index 0000000000..074958d671
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.table;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * For testing that UI scroll does not jump back to up when: 1. UI is in iframe
+ * 2. the window scrolled down 3. and table is clicked
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TableInIframeRowClickScrollJumpTest extends MultiBrowserTest {
+
+ private static final String TEST_URL = "statictestfiles/TableInIframeRowClickScrollJumpTest.html";
+
+ @Test
+ public void testRowClicking_WhenScrolledDown_shouldMaintainScrollPosition()
+ throws InterruptedException {
+ System.out.println(">>>" + getBaseURL() + TEST_URL);
+
+ driver.get(getUrl());
+
+ // using non-standard way because of iframe
+ sleep(4000);
+
+ // make sure we are in the "main content"
+ driver.switchTo().defaultContent();
+ sleep(2000);
+ switchIntoIframe();
+
+ // using non-standard way because of iframe
+ waitForElementVisible(By.id("scroll-button"));
+
+ ButtonElement scrollbutton = $(ButtonElement.class).id("scroll-button");
+ scrollbutton.click();
+
+ // using non-standard way because of iframe
+ sleep(1000);
+
+ Long scrollPosition = getWindowsScrollPosition();
+
+ assertThat("Scroll position should be greater than 100 (it was "
+ + scrollPosition + ")", scrollPosition > 100);
+
+ TableElement table = $(TableElement.class).first();
+ table.getRow(13).getCell(0).click();
+
+ // using non-standard way because of iframe
+ sleep(1000);
+
+ Long scrollPosition2 = getWindowsScrollPosition();
+
+ assertThat("Scroll position should stay about the same. Old was "
+ + scrollPosition + " and new one " + scrollPosition2,
+ Math.abs(scrollPosition - scrollPosition2) < 10);
+ }
+
+ private String getUrl() {
+ String url;
+ // using non-standard way because of iframe
+ if (getBaseURL().charAt(getBaseURL().length() - 1) == '/') {
+ url = getBaseURL() + TEST_URL;
+ } else {
+ // this one is for gerrit's teamcity :(
+ url = getBaseURL() + '/' + TEST_URL;
+ }
+ return url;
+ }
+
+ public void switchIntoIframe() {
+ List<WebElement> frames = driver.findElements(By.tagName("iframe"));
+ assertThat("No frames was found", frames.size() > 0);
+ driver.switchTo().frame(frames.get(0));
+ }
+
+ private Long getWindowsScrollPosition() {
+ // measure scroll pos in the main window
+ driver.switchTo().defaultContent();
+
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ Long value = (Long) executor
+ .executeScript("if (window.pageYOffset) return window.pageYOffset;else if (window.document.documentElement.scrollTop) return window.document.documentElement.scrollTop;else return window.document.body.scrollTop;");
+
+ // back to the iframe
+ switchIntoIframe();
+
+ return value;
+ }
+
+ @Override
+ // using non-standard way because of iframe
+ protected void closeApplication() {
+ if (driver != null) {
+ try {
+ driver.get(getUrl() + "?closeApplication");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}