Skip to content

Commit

Permalink
Focus the field in the the active cell when manually opening Grid editor
Browse files Browse the repository at this point in the history
Also move focus back to Grid when manually closing the editor.

Change-Id: I3ec54c00500ddd3872e7d20109191ac7db8bb950
  • Loading branch information
jdahlstrom authored and Vaadin Code Review committed May 28, 2015
1 parent 9f6cfbc commit 550bd1e
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 23 deletions.
90 changes: 70 additions & 20 deletions client/src/com/vaadin/client/widgets/Grid.java
Expand Up @@ -74,12 +74,14 @@
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.BrowserInfo; import com.vaadin.client.BrowserInfo;
import com.vaadin.client.DeferredWorker; import com.vaadin.client.DeferredWorker;
import com.vaadin.client.Focusable;
import com.vaadin.client.WidgetUtil; import com.vaadin.client.WidgetUtil;
import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.data.DataSource; import com.vaadin.client.data.DataSource;
import com.vaadin.client.renderers.ComplexRenderer; import com.vaadin.client.renderers.ComplexRenderer;
import com.vaadin.client.renderers.Renderer; import com.vaadin.client.renderers.Renderer;
import com.vaadin.client.renderers.WidgetRenderer; import com.vaadin.client.renderers.WidgetRenderer;
import com.vaadin.client.ui.FocusUtil;
import com.vaadin.client.ui.SubPartAware; import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.ui.dd.DragAndDropHandler; import com.vaadin.client.ui.dd.DragAndDropHandler;
import com.vaadin.client.widget.escalator.Cell; import com.vaadin.client.widget.escalator.Cell;
Expand Down Expand Up @@ -1131,6 +1133,7 @@ protected enum State {
private boolean enabled = false; private boolean enabled = false;
private State state = State.INACTIVE; private State state = State.INACTIVE;
private int rowIndex = -1; private int rowIndex = -1;
private int columnIndex = -1;
private String styleName = null; private String styleName = null;


private HandlerRegistration scrollHandler; private HandlerRegistration scrollHandler;
Expand Down Expand Up @@ -1196,8 +1199,11 @@ public void onSuccess(EditorRequest<T> request) {
state = State.ACTIVE; state = State.ACTIVE;
bindTimeout.cancel(); bindTimeout.cancel();


showOverlay(grid.getEscalator().getBody() assert rowIndex == request.getRowIndex() : "Request row index "
.getRowElement(request.getRowIndex())); + request.getRowIndex()
+ " did not match the saved row index " + rowIndex;

showOverlay();
} }
} }


Expand Down Expand Up @@ -1257,17 +1263,33 @@ public int getRow() {
} }


/** /**
* Opens the editor over the row with the given index. * Equivalent to {@code editRow(rowIndex, -1)}.
*
* @see #editRow(int, int)
*/
public void editRow(int rowIndex) {
editRow(rowIndex, -1);
}

/**
* Opens the editor over the row with the given index and attempts to
* focus the editor widget in the given column index. Does not move
* focus if the widget is not focusable or if the column index is -1.
* *
* @param rowIndex * @param rowIndex
* the index of the row to be edited * the index of the row to be edited
* @param columnIndex
* the column index of the editor widget that should be
* initially focused or -1 to not set focus
* *
* @throws IllegalStateException * @throws IllegalStateException
* if this editor is not enabled * if this editor is not enabled
* @throws IllegalStateException * @throws IllegalStateException
* if this editor is already in edit mode * if this editor is already in edit mode
*
* @since
*/ */
public void editRow(int rowIndex) { public void editRow(int rowIndex, int columnIndex) {
if (!enabled) { if (!enabled) {
throw new IllegalStateException( throw new IllegalStateException(
"Cannot edit row: editor is not enabled"); "Cannot edit row: editor is not enabled");
Expand All @@ -1278,6 +1300,7 @@ public void editRow(int rowIndex) {
} }


this.rowIndex = rowIndex; this.rowIndex = rowIndex;
this.columnIndex = columnIndex;


state = State.ACTIVATING; state = State.ACTIVATING;


Expand Down Expand Up @@ -1457,15 +1480,31 @@ protected Widget getWidget(Column<?, T> column) {
} }


/** /**
* Opens the editor overlay over the given table row. * Equivalent to {@code showOverlay()}. The argument is ignored.
*
* @param unused
* ignored argument
* *
* @param tr * @deprecated As of 7.5, use {@link #showOverlay()} instead.
* the row to be edited
*/ */
protected void showOverlay(TableRowElement tr) { @Deprecated
protected void showOverlay(TableRowElement unused) {
showOverlay();
}

/**
* Opens the editor overlay over the table row indicated by
* {@link #getRow()}.
*
* @since
*/
protected void showOverlay() {


DivElement gridElement = DivElement.as(grid.getElement()); DivElement gridElement = DivElement.as(grid.getElement());


TableRowElement tr = grid.getEscalator().getBody()
.getRowElement(rowIndex);

scrollHandler = grid.addScrollHandler(new ScrollHandler() { scrollHandler = grid.addScrollHandler(new ScrollHandler() {
@Override @Override
public void onScroll(ScrollEvent event) { public void onScroll(ScrollEvent event) {
Expand All @@ -1485,10 +1524,20 @@ public void onScroll(ScrollEvent event) {
Column<?, T> column = grid.getVisibleColumn(i); Column<?, T> column = grid.getVisibleColumn(i);
if (column.isEditable()) { if (column.isEditable()) {
Widget editor = getHandler().getWidget(column); Widget editor = getHandler().getWidget(column);

if (editor != null) { if (editor != null) {
columnToWidget.put(column, editor); columnToWidget.put(column, editor);
attachWidget(editor, cell); attachWidget(editor, cell);
} }

if (i == columnIndex) {
if (editor instanceof Focusable) {
((Focusable) editor).focus();
} else if (editor instanceof com.google.gwt.user.client.ui.Focusable) {
((com.google.gwt.user.client.ui.Focusable) editor)
.setFocus(true);
}
}
} else { } else {
cell.addClassName(NOT_EDITABLE_CLASS_NAME); cell.addClassName(NOT_EDITABLE_CLASS_NAME);
} }
Expand Down Expand Up @@ -1521,7 +1570,7 @@ public void onScroll(ScrollEvent event) {
// Move message and buttons wrapper on top of cell wrapper if // Move message and buttons wrapper on top of cell wrapper if
// there is not enough space visible space under and fix the // there is not enough space visible space under and fix the
// overlay from the bottom // overlay from the bottom
editorOverlay.appendChild(cellWrapper); editorOverlay.insertFirst(messageAndButtonsWrapper);
int gridHeight = grid.getElement().getOffsetHeight(); int gridHeight = grid.getElement().getOffsetHeight();
editorOverlay.getStyle() editorOverlay.getStyle()
.setBottom( .setBottom(
Expand Down Expand Up @@ -6309,24 +6358,25 @@ private boolean isElementInChildWidget(Element e) {


private boolean handleEditorEvent(Event event, RowContainer container) { private boolean handleEditorEvent(Event event, RowContainer container) {


final boolean closeEvent = event.getTypeInt() == Event.ONKEYDOWN
&& event.getKeyCode() == Editor.KEYCODE_HIDE;
final boolean openEvent = event.getTypeInt() == Event.ONDBLCLICK
|| (event.getTypeInt() == Event.ONKEYDOWN && event.getKeyCode() == Editor.KEYCODE_SHOW);

if (editor.getState() != Editor.State.INACTIVE) { if (editor.getState() != Editor.State.INACTIVE) {
if (event.getTypeInt() == Event.ONKEYDOWN if (closeEvent) {
&& event.getKeyCode() == Editor.KEYCODE_HIDE) {
editor.cancel(); editor.cancel();
FocusUtil.setFocus(this, true);
} }
return true; return true;
} }


if (container == escalator.getBody() && editor.isEnabled()) { if (container == escalator.getBody() && editor.isEnabled() && openEvent) {
if (event.getTypeInt() == Event.ONDBLCLICK) { editor.editRow(eventCell.getRowIndex(),
editor.editRow(eventCell.getRowIndex()); eventCell.getColumnIndexDOM());
return true; return true;
} else if (event.getTypeInt() == Event.ONKEYDOWN
&& event.getKeyCode() == Editor.KEYCODE_SHOW) {
editor.editRow(cellFocusHandler.rowWithFocus);
return true;
}
} }

return false; return false;
} }


Expand Down
Expand Up @@ -33,6 +33,7 @@
import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.interactions.Actions;


import com.vaadin.shared.ui.grid.GridConstants; import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.testbench.elements.GridElement.GridCellElement;
import com.vaadin.testbench.elements.GridElement.GridEditorElement; import com.vaadin.testbench.elements.GridElement.GridEditorElement;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
Expand Down Expand Up @@ -73,6 +74,22 @@ public void testVerticalScrollLocking() {
getGridElement().getCell(200, 0); getGridElement().getCell(200, 0);
} }


@Test
public void testMouseOpeningClosing() {

getGridElement().getCell(4, 0).doubleClick();
assertNotNull(getEditor());

getCancelButton().click();
assertNull(getEditor());

// Disable editor
selectMenuPath("Component", "Editor", "Enabled");

getGridElement().getCell(4, 0).doubleClick();
assertNull(getEditor());
}

@Test @Test
public void testKeyboardOpeningClosing() { public void testKeyboardOpeningClosing() {


Expand Down Expand Up @@ -219,6 +236,44 @@ public void testErrorField() {
editor.getErrorMessage()); editor.getErrorMessage());
} }


@Test
public void testFocusOnMouseOpen() {

GridCellElement cell = getGridElement().getCell(4, 2);

cell.doubleClick();

WebElement focused = getFocusedElement();

assertEquals("", "input", focused.getTagName());
assertEquals("", cell.getText(), focused.getAttribute("value"));
}

@Test
public void testFocusOnKeyboardOpen() {

GridCellElement cell = getGridElement().getCell(4, 2);

cell.click();
new Actions(getDriver()).sendKeys(Keys.ENTER).perform();

WebElement focused = getFocusedElement();

assertEquals("", "input", focused.getTagName());
assertEquals("", cell.getText(), focused.getAttribute("value"));
}

@Test
public void testNoFocusOnProgrammaticOpen() {

selectMenuPath(EDIT_ROW_5);

WebElement focused = getFocusedElement();

// GWT menubar loses focus after clicking a menuitem
assertEquals("Focus should be in body", "body", focused.getTagName());
}

protected WebElement getSaveButton() { protected WebElement getSaveButton() {
return getEditor().findElement(By.className("v-grid-editor-save")); return getEditor().findElement(By.className("v-grid-editor-save"));
} }
Expand Down
Expand Up @@ -94,6 +94,20 @@ public void testVerticalScrollLocking() {
getGridElement().getCell(200, 0); getGridElement().getCell(200, 0);
} }


@Test
public void testMouseOpeningClosing() {

getGridElement().getCell(4, 0).doubleClick();
assertEditorOpen();

getCancelButton().click();
assertEditorClosed();

selectMenuPath(TOGGLE_EDIT_ENABLED);
getGridElement().getCell(4, 0).doubleClick();
assertEditorClosed();
}

@Test @Test
public void testKeyboardOpeningClosing() { public void testKeyboardOpeningClosing() {


Expand Down Expand Up @@ -234,7 +248,7 @@ public void testInvalidEdition() {
} }


@Test @Test
public void testNoScrollAfterEditByAPI() { public void testNoScrollAfterProgrammaticOpen() {
int originalScrollPos = getGridVerticalScrollPos(); int originalScrollPos = getGridVerticalScrollPos();


selectMenuPath(EDIT_ITEM_5); selectMenuPath(EDIT_ITEM_5);
Expand All @@ -245,7 +259,7 @@ public void testNoScrollAfterEditByAPI() {
} }


@Test @Test
public void testNoScrollAfterEditByMouse() { public void testNoScrollAfterMouseOpen() {
int originalScrollPos = getGridVerticalScrollPos(); int originalScrollPos = getGridVerticalScrollPos();


GridCellElement cell_5_0 = getGridElement().getCell(5, 0); GridCellElement cell_5_0 = getGridElement().getCell(5, 0);
Expand All @@ -257,7 +271,7 @@ public void testNoScrollAfterEditByMouse() {
} }


@Test @Test
public void testNoScrollAfterEditByKeyboard() { public void testNoScrollAfterKeyboardOpen() {
int originalScrollPos = getGridVerticalScrollPos(); int originalScrollPos = getGridVerticalScrollPos();


GridCellElement cell_5_0 = getGridElement().getCell(5, 0); GridCellElement cell_5_0 = getGridElement().getCell(5, 0);
Expand Down Expand Up @@ -293,6 +307,49 @@ public void testEditorInDisabledGrid() {
originalScrollPos, getGridVerticalScrollPos()); originalScrollPos, getGridVerticalScrollPos());
} }


@Test
public void testFocusOnMouseOpen() {

GridCellElement cell = getGridElement().getCell(4, 2);

cell.doubleClick();

WebElement focused = getFocusedElement();

assertEquals("", "input", focused.getTagName());
assertEquals("", cell.getText(), focused.getAttribute("value"));
}

@Test
public void testFocusOnKeyboardOpen() {

GridCellElement cell = getGridElement().getCell(4, 2);

cell.click();
new Actions(getDriver()).sendKeys(Keys.ENTER).perform();

WebElement focused = getFocusedElement();

assertEquals("", "input", focused.getTagName());
assertEquals("", cell.getText(), focused.getAttribute("value"));
}

@Test
public void testNoFocusOnProgrammaticOpen() {

selectMenuPath(EDIT_ITEM_5);

WebElement focused = getFocusedElement();

assertEquals("Focus should remain in the menu", "menu",
focused.getAttribute("id"));
}

@Override
protected WebElement getFocusedElement() {
return (WebElement) executeScript("return document.activeElement;");
}

@Test @Test
public void testUneditableColumn() { public void testUneditableColumn() {
selectMenuPath(EDIT_ITEM_5); selectMenuPath(EDIT_ITEM_5);
Expand Down
Expand Up @@ -98,6 +98,7 @@ public static class Menu {
private Menu() { private Menu() {
title = ""; title = "";
menubar = new MenuBar(); menubar = new MenuBar();
menubar.getElement().setId("menu");
children = new ArrayList<Menu>(); children = new ArrayList<Menu>();
items = new ArrayList<Command>(); items = new ArrayList<Command>();
} }
Expand Down

0 comments on commit 550bd1e

Please sign in to comment.