* its parents are) removed from the document. Therefore, we sort
* everything around that row instead.
*/
- final TableRowElement focusedRow = getEscalatorRowWithFocus();
+ final TableRowElement focusedRow = getRowWithFocus();
if (focusedRow != null) {
assert focusedRow.getParentElement() == root : "Trying to sort around a row that doesn't exist in body";
- assert visualRowOrder.contains(focusedRow) : "Trying to sort around a row that doesn't exist in visualRowOrder.";
+ assert visualRowOrder.contains(focusedRow)
+ || body.spacerContainer.isSpacer(focusedRow) : "Trying to sort around a row that doesn't exist in visualRowOrder or is not a spacer.";
}
/*
* the first child.
*/
+ List<TableRowElement> orderedBodyRows = new ArrayList<TableRowElement>(
+ visualRowOrder);
+ for (int i = 0; i < visualRowOrder.size(); i++) {
+ SpacerContainer.SpacerImpl spacer = body.spacerContainer
+ .getSpacer(getTopRowLogicalIndex() + i);
+
+ if (spacer != null) {
+ orderedBodyRows.add(i + 1, spacer.getRootElement());
+ }
+ }
+ /*
+ * At this point, invisible spacers aren't reordered, so their
+ * position in the DOM is undefined.
+ */
+
/*
* If we have a focused row, start in the mode where we put
* everything underneath that row. Otherwise, all rows are placed as
*/
boolean insertFirst = (focusedRow == null);
- final ListIterator<TableRowElement> i = visualRowOrder
- .listIterator(visualRowOrder.size());
+ final ListIterator<TableRowElement> i = orderedBodyRows
+ .listIterator(orderedBodyRows.size());
while (i.hasPrevious()) {
TableRowElement tr = i.previous();
}
/**
- * Get the escalator row that has focus.
+ * Get the {@literal <tbody>} row that contains (or has) focus.
*
- * @return The escalator row that contains a focused DOM element, or
- * <code>null</code> if focus is outside of a body row.
+ * @return The {@literal <tbody>} row that contains a focused DOM
+ * element, or <code>null</code> if focus is outside of a body
+ * row.
*/
- private TableRowElement getEscalatorRowWithFocus() {
+ private TableRowElement getRowWithFocus() {
TableRowElement rowContainingFocus = null;
final Element focusedElement = WidgetUtil.getFocusedElement();
}
}
+ /** Checks if a given element is a spacer element */
+ public boolean isSpacer(TableRowElement focusedRow) {
+
+ /*
+ * If this needs optimization, we could do a more heuristic check
+ * based on stylenames and stuff, instead of iterating through the
+ * map.
+ */
+
+ for (SpacerImpl spacer : rowIndexToSpacer.values()) {
+ if (spacer.getRootElement().equals(focusedRow)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@SuppressWarnings("boxing")
void scrollToSpacer(int spacerIndex, ScrollDestination destination,
int padding) {
spacer.setupDom(height);
initSpacerContent(spacer);
+
+ body.sortDomElements();
}
private void updateExistingSpacer(int rowIndex, double newHeight) {
protected static final String COLSPAN_NONE = "Apply no colspan";
protected static final String SET_100PX = "Set 100px";
protected static final String SPACERS = "Spacers";
+ protected static final String FOCUSABLE_UPDATER = "Focusable Updater";
protected static final String SCROLL_HERE_ANY_0PADDING = "Scroll here (ANY, 0)";
protected static final String SCROLL_HERE_SPACERBELOW_ANY_0PADDING = "Scroll here row+spacer below (ANY, 0)";
protected static final String REMOVE = "Remove";
import org.junit.Before;
import org.junit.ComparisonFailure;
import org.junit.Test;
+import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.vaadin.client.WidgetUtil;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.testbench.parallel.BrowserUtil;
import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
@SuppressWarnings("boxing")
@Before
public void before() {
+ setDebug(true);
openTestURL();
selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, "Set 20px default height");
populate();
assertEquals(getScrollTop(), 950);
}
+ @Test
+ public void domCanBeSortedWithFocusInSpacer() throws InterruptedException {
+
+ // Firefox behaves badly with focus-related tests - skip it.
+ if (BrowserUtil.isFirefox(super.getDesiredCapabilities())) {
+ return;
+ }
+
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ WebElement inputElement = getEscalator().findElement(
+ By.tagName("input"));
+ inputElement.click();
+ scrollVerticallyTo(30);
+
+ // Sleep needed because of all the JS we're doing, and to let
+ // the DOM reordering to take place.
+ Thread.sleep(500);
+
+ assertFalse("Error message detected", $(NotificationElement.class)
+ .exists());
+ }
+
+ @Test
+ public void spacersAreInsertedInCorrectDomPosition() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ WebElement tbody = getEscalator().findElement(By.tagName("tbody"));
+ WebElement spacer = getChild(tbody, 2);
+ String cssClass = spacer.getAttribute("class");
+ assertTrue("element index 2 was not a spacer (class=\"" + cssClass
+ + "\")", cssClass.contains("-spacer"));
+ }
+
+ @Test
+ public void spacersAreInCorrectDomPositionAfterScroll() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ scrollVerticallyTo(30); // roughly one row's worth
+
+ WebElement tbody = getEscalator().findElement(By.tagName("tbody"));
+ WebElement spacer = getChild(tbody, 1);
+ String cssClass = spacer.getAttribute("class");
+ assertTrue("element index 1 was not a spacer (class=\"" + cssClass
+ + "\")", cssClass.contains("-spacer"));
+ }
+
+ private WebElement getChild(WebElement parent, int childIndex) {
+ return (WebElement) executeScript("return arguments[0].children["
+ + childIndex + "];", parent);
+ }
+
private static double[] getElementDimensions(WebElement element) {
/*
* we need to parse the style attribute, since using getCssValue gets a
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.TableCellElement;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.vaadin.client.widget.escalator.EscalatorUpdater;
public void execute() {
BodyRowContainer body = escalator.getBody();
- if (body.getSpacerUpdater().equals(SpacerUpdater.NULL)) {
+ if (SpacerUpdater.NULL.equals(body.getSpacerUpdater())) {
body.setSpacerUpdater(CUSTOM);
} else {
body.setSpacerUpdater(SpacerUpdater.NULL);
}
}, menupath);
+ addMenuCommand("Focusable Updater", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setSpacerUpdater(new SpacerUpdater() {
+ @Override
+ public void init(Spacer spacer) {
+ spacer.getElement().appendChild(DOM.createInputText());
+ }
+
+ @Override
+ public void destroy(Spacer spacer) {
+ spacer.getElement().removeAllChildren();
+ }
+ });
+ }
+ }, menupath);
+
createSpacersMenuForRow(-1, menupath);
createSpacersMenuForRow(1, menupath);
createSpacersMenuForRow(50, menupath);