Browse Source

Fix for navigating in Grid using Tab

tags/8.5.0.alpha1
Teemu Suo-Anttila 6 years ago
parent
commit
07c6456da8

+ 3
- 1
client/src/main/java/com/vaadin/client/WidgetUtil.java View File

@@ -916,8 +916,10 @@ public class WidgetUtil {
EventListener eventListener = null;
while (eventListener == null && element != null) {
eventListener = Event.getEventListener(element);
if (eventListener == null) {
if (eventListener == null
|| !(eventListener instanceof Widget)) {
element = element.getParentElement();
eventListener = null;
}
}
if (eventListener instanceof Widget) {

+ 35
- 0
client/src/main/java/com/vaadin/client/widgets/Escalator.java View File

@@ -30,6 +30,7 @@ import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.animation.client.AnimationScheduler;
@@ -53,9 +54,11 @@ import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.logging.client.LogConfiguration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.RootPanel;
@@ -5823,6 +5826,38 @@ public class Escalator extends Widget

tableWrapper = DivElement.as(DOM.createDiv());

Event.sinkEvents(tableWrapper, Event.ONSCROLL | Event.KEYEVENTS);

Event.setEventListener(tableWrapper, event -> {
if (event.getKeyCode() != KeyCodes.KEY_TAB) {
return;
}

boolean browserScroll = tableWrapper.getScrollLeft() != 0
|| tableWrapper.getScrollTop() != 0;
boolean keyEvent = event.getType().startsWith("key");

if (browserScroll || keyEvent) {

// Browser is scrolling our div automatically, reset
tableWrapper.setScrollLeft(0);
tableWrapper.setScrollTop(0);

Element focused = WidgetUtil.getFocusedElement();
Stream.of(header, body, footer).forEach(container -> {
Cell cell = container.getCell(focused);
if (cell == null) {
return;
}

scrollToColumn(cell.getColumn(), ScrollDestination.ANY, 0);
if (container == body) {
scrollToRow(cell.getRow(), ScrollDestination.ANY, 0);
}
});
}
});

root.appendChild(tableWrapper);

table = DOM.createTable();

+ 10
- 2
uitest/src/main/java/com/vaadin/tests/components/grid/GridComponents.java View File

@@ -76,7 +76,15 @@ public class GridComponents extends AbstractTestUIWithLog {
resetData.click();
addComponent(resetData);

grid.appendHeaderRow().join("label", "textField", "button").setComponent(new TextField());
grid.appendFooterRow().join("label", "textField", "button").setComponent(new TextField());
TextField headerField = new TextField();
TextField footerField = new TextField();

headerField.setId("headerField");
footerField.setId("footerField");

grid.appendHeaderRow().join("label", "textField", "button")
.setComponent(headerField);
grid.appendFooterRow().join("label", "textField", "button")
.setComponent(footerField);
}
}

+ 80
- 2
uitest/src/test/java/com/vaadin/tests/components/grid/GridComponentsTest.java View File

@@ -11,9 +11,9 @@ import java.util.stream.Stream;
import org.junit.Test;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;

import com.vaadin.testbench.By;
import com.vaadin.testbench.annotations.RunLocally;
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.GridElement;
import com.vaadin.testbench.elements.GridElement.GridCellElement;
@@ -21,7 +21,6 @@ import com.vaadin.testbench.elements.GridElement.GridRowElement;
import com.vaadin.testbench.elements.LabelElement;
import com.vaadin.testbench.elements.NotificationElement;
import com.vaadin.testbench.elements.TextFieldElement;
import com.vaadin.testbench.parallel.Browser;
import com.vaadin.testbench.parallel.BrowserUtil;
import com.vaadin.tests.tb3.MultiBrowserTest;

@@ -185,6 +184,85 @@ public class GridComponentsTest extends MultiBrowserTest {

}

@Test
public void testTabNavigation() {
openTestURL();

GridElement grid = $(GridElement.class).first();
WebElement resizeHandle = grid.getHeaderCell(0, 0)
.findElement(By.cssSelector("div.v-grid-column-resize-handle"));

new Actions(getDriver()).moveToElement(resizeHandle).clickAndHold()
.moveByOffset(440, 0).release().perform();

// Scroll to end
grid.getCell(0, 2);
int scrollMax = getScrollLeft(grid);
assertTrue("Width of the grid too narrow, no scroll bar",
scrollMax > 0);

// Scroll to start
grid.getHorizontalScroller().scrollLeft(0);

assertEquals(
"Grid should scrolled to the start for this part of the test..",
0, getScrollLeft(grid));

// Focus TextField in second column
WebElement textField = grid.getCell(0, 1)
.findElement(By.tagName("input"));
textField.click();

// Navigate to currently out of viewport Button
new Actions(getDriver()).sendKeys(Keys.TAB).perform();
assertEquals("Grid should be scrolled to the end", scrollMax,
getScrollLeft(grid));

// Navigate back to fully visible TextField
new Actions(getDriver()).sendKeys(Keys.chord(Keys.SHIFT, Keys.TAB))
.perform();
assertEquals(
"Grid should not scroll when focusing the text field again. ",
scrollMax, getScrollLeft(grid));

// Navigate to out of viewport TextField in Header
new Actions(getDriver()).sendKeys(Keys.chord(Keys.SHIFT, Keys.TAB))
.perform();
assertEquals("Focus should be in TextField in Header", "headerField",
getFocusedElement().getAttribute("id"));
assertEquals("Grid should've scrolled back to start.", 0,
getScrollLeft(grid));

// Focus button in last visible row of Grid
grid.getCell(6, 2).findElement(By.id("row_6")).click();

// Navigate to currently out of viewport TextField on Row 7
new Actions(getDriver()).sendKeys(Keys.TAB).perform();
int scrollTopRow7 = Integer
.parseInt(grid.getVerticalScroller().getAttribute("scrollTop"));
assertTrue("Grid should be scrolled to show row 7", scrollTopRow7 > 0);

// Navigate to currently out of viewport TextField on Row 8
new Actions(getDriver()).sendKeys(Keys.TAB, Keys.TAB).perform();
assertTrue("Grid should be scrolled to show row 7",
Integer.parseInt(grid.getVerticalScroller()
.getAttribute("scrollTop")) > scrollTopRow7);

// Focus button in last row of Grid
grid.getCell(999, 2).findElement(By.id("row_999")).click();
// Navigate to out of viewport TextField in Footer
new Actions(getDriver()).sendKeys(Keys.TAB).perform();
assertEquals("Focus should be in TextField in Footer", "footerField",
getFocusedElement().getAttribute("id"));
assertEquals("Grid should've scrolled horizontally back to start.", 0,
getScrollLeft(grid));
}

private int getScrollLeft(GridElement grid) {
return Integer.parseInt(
grid.getHorizontalScroller().getAttribute("scrollLeft"));
}

private void assertRowExists(int i, String string) {
GridRowElement row = $(GridElement.class).first().getRow(i);
assertEquals("Label text did not match", string,

Loading…
Cancel
Save