From 034b61de038532aa4f444e3a4740da75459f8dda Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Sat, 16 Apr 2016 13:47:26 +0300 Subject: Take body scrolling into account when deciding combobox popup position (#19162) For standard standalone Vaadin apps, the body scroll is not scrollable. For these this change should have no effect. In embedded cases and when running as portlet, the body is scrollable. For these cases, the popup is now correctly shown below the combo box when there is space. Change-Id: Ia183f4f2988e6593634f6e9735fd58abbd4a1da1 --- .../java/com/vaadin/client/ui/VFilterSelect.java | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'client') diff --git a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java b/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java index 8a6b442fb8..9fb6d18ac5 100644 --- a/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java +++ b/client/src/main/java/com/vaadin/client/ui/VFilterSelect.java @@ -28,6 +28,7 @@ import com.google.gwt.aria.client.Roles; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style; @@ -657,7 +658,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, debug("VFS.SP: setPosition(" + offsetWidth + ", " + offsetHeight + ")"); - int top = topPosition; + int top; int left = getPopupLeft(); // reset menu size and retrieve its "natural" size @@ -705,19 +706,31 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler, getContainerElement().getStyle().setWidth(rootWidth, Unit.PX); } - final int vfsHeight = VFilterSelect.this.getOffsetHeight(); - final int spaceAvailableAbove = top - vfsHeight; - final int spaceAvailableBelow = Window.getClientHeight() - top; - if (spaceAvailableBelow < offsetHeight - && spaceAvailableBelow < spaceAvailableAbove) { + final int textInputHeight = VFilterSelect.this.getOffsetHeight(); + final int textInputTopOnPage = tb.getAbsoluteTop(); + final int viewportOffset = Document.get().getScrollTop(); + final int textInputTopInViewport = textInputTopOnPage + - viewportOffset; + final int textInputBottomInViewport = textInputTopInViewport + + textInputHeight; + + final int spaceAboveInViewport = textInputTopInViewport; + final int spaceBelowInViewport = Window.getClientHeight() + - textInputBottomInViewport; + + if (spaceBelowInViewport < offsetHeight + && spaceBelowInViewport < spaceAboveInViewport) { // popup on top of input instead - top -= offsetHeight + vfsHeight; - if (top < 0) { - offsetHeight += top; - top = 0; + if (offsetHeight > spaceAboveInViewport) { + // Shrink popup height to fit above + offsetHeight = spaceAboveInViewport; } + top = textInputTopOnPage - offsetHeight; } else { - offsetHeight = Math.min(offsetHeight, spaceAvailableBelow); + // Show below, position calculated in showSuggestions for some + // strange reason + top = topPosition; + offsetHeight = Math.min(offsetHeight, spaceBelowInViewport); } // fetch real width (mac FF bugs here due GWT popups overflow:auto ) -- cgit v1.2.3