Browse Source

Fixed scroll jump by using native focusing in IE (#15294)

Change-Id: I412ba219f31567ebba019b7d6ce4db4af9be9363
tags/7.5.0.beta1
Johannes Tuikkala 9 years ago
parent
commit
1c569304b3

+ 12
- 0
WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html View File

@@ -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>

+ 8
- 0
client/src/com/vaadin/client/ui/FocusableScrollPanel.java View File

@@ -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);

+ 153
- 0
uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java View File

@@ -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;
}

}

+ 64
- 0
uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java View File

@@ -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;
}
}

+ 127
- 0
uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java View File

@@ -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();
}
}
}
}

Loading…
Cancel
Save