diff options
author | Johannes Tuikkala <johannes@vaadin.com> | 2015-03-05 13:32:33 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2015-03-26 16:16:52 +0200 |
commit | 7f253a23f696f1cdee2abae1b7558993eea65915 (patch) | |
tree | 33f10bc68a72fb18b3cdaed0d2c8baca3dc461a6 | |
parent | cb53601d9bc9be366635df51a8f9af3e92d3c5c7 (diff) | |
download | vaadin-framework-7f253a23f696f1cdee2abae1b7558993eea65915.tar.gz vaadin-framework-7f253a23f696f1cdee2abae1b7558993eea65915.zip |
Fixed scroll jump by using native focusing in IE (#15294)
Change-Id: I412ba219f31567ebba019b7d6ce4db4af9be9363
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(); + } + } + } +} |