summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-05-10 16:53:33 +0300
committerLeif Åstrand <leif@vaadin.com>2013-05-10 16:53:33 +0300
commit42d94768bfacb3d831e125ae33eeb4b9fa1d8a53 (patch)
treea09cd9d99d1be99dd6600a90db07fb08d15af28a
parent762c924a8bf05f57b8af7108d7bb6a9c59dcc6c6 (diff)
parent19e27a15ca765de477fbe929a1cb6a7412c523f7 (diff)
downloadvaadin-framework-42d94768bfacb3d831e125ae33eeb4b9fa1d8a53.tar.gz
vaadin-framework-42d94768bfacb3d831e125ae33eeb4b9fa1d8a53.zip
Merge changes from origin/7.0
7d9f544 Test for #11396 (merged from 6.8 branch). Depends on a blur event so cannot be autotested with TB. 1b18807 Remove pre-loader element after pre-loading, fixes #10863 ce9c818 Instead of applying workaround to the root panel, apply it to the sub window content element instead to prevent scrolling of the document when a sub window is removed. #11713 (#10776) 3f5d022 Liferay 6.2 compatibility (#11751) ffd1c1b Don't ignore child component margins in AbstractOrderedLayout (#11553) 62ae5e1 More verbose output from running Jetty 21d9b67 Add a large number of debug calls to VFilterSelect (disabled by default) bdb7931 Merge test for #11623 to 7.0. 19e27a1 Move suggestion popup width calculation from connector to VFilterSelect Change-Id: I2d980126599e55fa5e4f6ec523dca16ba54107b5
-rw-r--r--client/src/com/vaadin/client/ResourceLoader.java18
-rw-r--r--client/src/com/vaadin/client/ui/VFilterSelect.java108
-rw-r--r--client/src/com/vaadin/client/ui/VWindow.java24
-rw-r--r--client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java14
-rw-r--r--client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java16
-rw-r--r--server/src/com/vaadin/server/VaadinPortlet.java69
-rw-r--r--tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html72
-rw-r--r--uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java109
-rw-r--r--uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java29
-rw-r--r--uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java69
-rw-r--r--uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html27
-rw-r--r--uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java85
-rw-r--r--uitest/test.xml1
-rw-r--r--uitest/vaadin-server.xml3
14 files changed, 592 insertions, 52 deletions
diff --git a/client/src/com/vaadin/client/ResourceLoader.java b/client/src/com/vaadin/client/ResourceLoader.java
index b3b9ac7256..7fc8b4f9f3 100644
--- a/client/src/com/vaadin/client/ResourceLoader.java
+++ b/client/src/com/vaadin/client/ResourceLoader.java
@@ -50,8 +50,8 @@ public class ResourceLoader {
* Event fired when a resource has been loaded.
*/
public static class ResourceLoadEvent {
- private ResourceLoader loader;
- private String resourceUrl;
+ private final ResourceLoader loader;
+ private final String resourceUrl;
private final boolean preload;
/**
@@ -286,25 +286,35 @@ public class ResourceLoader {
// Inject loader element if this is the first time this is preloaded
// AND the resources isn't already being loaded in the normal way
- Element element = getPreloadElement(url);
+ final Element element = getPreloadElement(url);
addOnloadHandler(element, new ResourceLoadListener() {
@Override
public void onLoad(ResourceLoadEvent event) {
fireLoad(event);
+ Document.get().getBody().removeChild(element);
}
@Override
public void onError(ResourceLoadEvent event) {
fireError(event);
+ Document.get().getBody().removeChild(element);
}
}, event);
- // TODO Remove object when loaded (without causing spinner in FF)
Document.get().getBody().appendChild(element);
}
}
private static Element getPreloadElement(String url) {
+ /*-
+ * TODO
+ * In Chrome, FF:
+ * <object> does not fire event if resource is 404 -> eternal spinner.
+ * <img> always fires onerror -> no way to know if it loaded -> eternal spinner
+ * <script type="text/javascript> fires, but also executes -> not preloading
+ * <script type="text/cache"> does not fire events
+ * XHR not tested - should work, probably causes other issues
+ -*/
if (BrowserInfo.get().isIE()) {
ScriptElement element = Document.get().createScriptElement();
element.setSrc(url);
diff --git a/client/src/com/vaadin/client/ui/VFilterSelect.java b/client/src/com/vaadin/client/ui/VFilterSelect.java
index 5ec7039462..05535686d5 100644
--- a/client/src/com/vaadin/client/ui/VFilterSelect.java
+++ b/client/src/com/vaadin/client/ui/VFilterSelect.java
@@ -205,6 +205,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*/
SuggestionPopup() {
super(true, false, true);
+ debug("VFS.SP: constructor()");
setOwner(VFilterSelect.this);
menu = new SuggestionMenu();
setWidget(menu);
@@ -243,6 +244,11 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
final Collection<FilterSelectSuggestion> currentSuggestions,
final int currentPage, final int totalSuggestions) {
+ if (enableDebug) {
+ debug("VFS.SP: showSuggestions(" + currentSuggestions + ", "
+ + currentPage + ", " + totalSuggestions + ")");
+ }
+
/*
* We need to defer the opening of the popup so that the parent DOM
* has stabilized so we can calculate an absolute top and left
@@ -310,6 +316,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @param active
*/
private void setNextButtonActive(boolean active) {
+ if (enableDebug) {
+ debug("VFS.SP: setNextButtonActive(" + active + ")");
+ }
if (active) {
DOM.sinkEvents(down, Event.ONCLICK);
down.setClassName(VFilterSelect.this.getStylePrimaryName()
@@ -327,6 +336,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @param active
*/
private void setPrevButtonActive(boolean active) {
+ if (enableDebug) {
+ debug("VFS.SP: setPrevButtonActive(" + active + ")");
+ }
+
if (active) {
DOM.sinkEvents(up, Event.ONCLICK);
up.setClassName(VFilterSelect.this.getStylePrimaryName()
@@ -343,6 +356,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Selects the next item in the filtered selections
*/
public void selectNextItem() {
+ debug("VFS.SP: selectNextItem()");
final MenuItem cur = menu.getSelectedItem();
final int index = 1 + menu.getItems().indexOf(cur);
if (menu.getItems().size() > index) {
@@ -362,6 +376,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Selects the previous item in the filtered selections
*/
public void selectPrevItem() {
+ debug("VFS.SP: selectPrevItem()");
final MenuItem cur = menu.getSelectedItem();
final int index = -1 + menu.getItems().indexOf(cur);
if (index > -1) {
@@ -396,6 +411,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void run() {
+ debug("VFS.SP.LPS: run()");
if (pagesToScroll != 0) {
if (!waitingForFilteringResponse) {
/*
@@ -416,6 +432,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
public void scrollUp() {
+ debug("VFS.SP.LPS: scrollUp()");
if (currentPage + pagesToScroll > 0) {
pagesToScroll--;
cancel();
@@ -424,6 +441,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
public void scrollDown() {
+ debug("VFS.SP.LPS: scrollDown()");
if (totalMatches > (currentPage + pagesToScroll + 1)
* pageLength) {
pagesToScroll++;
@@ -443,6 +461,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onBrowserEvent(Event event) {
+ debug("VFS.SP: onBrowserEvent()");
if (event.getTypeInt() == Event.ONCLICK) {
final Element target = DOM.eventGetTarget(event);
if (target == up || target == DOM.getChild(up, 0)) {
@@ -476,6 +495,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Should the paging be turned on?
*/
public void setPagingEnabled(boolean paging) {
+ debug("VFS.SP: setPagingEnabled(" + paging + ")");
if (isPagingEnabled == paging) {
return;
}
@@ -501,6 +521,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
+ debug("VFS.SP: setPosition()");
int top = -1;
int left = -1;
@@ -579,6 +600,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @return true if popup was just closed
*/
public boolean isJustClosed() {
+ debug("VFS.SP: justClosed()");
final long now = (new Date()).getTime();
return (lastAutoClosed > 0 && (now - lastAutoClosed) < 200);
}
@@ -593,6 +615,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onClose(CloseEvent<PopupPanel> event) {
+ if (enableDebug) {
+ debug("VFS.SP: onClose(" + event.isAutoClosed() + ")");
+ }
if (event.isAutoClosed()) {
lastAutoClosed = (new Date()).getTime();
}
@@ -608,6 +633,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*/
public void updateStyleNames(UIDL uidl,
AbstractComponentState componentState) {
+ debug("VFS.SP: updateStyleNames()");
setStyleName(VFilterSelect.this.getStylePrimaryName()
+ "-suggestpopup");
menu.setStyleName(VFilterSelect.this.getStylePrimaryName()
@@ -643,6 +669,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void execute() {
+ debug("VFS.SM: delayedImageLoadExecutioner()");
if (suggestionPopup.isVisible()
&& suggestionPopup.isAttached()) {
setWidth("");
@@ -660,6 +687,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*/
SuggestionMenu() {
super(true);
+ debug("VFS.SM: constructor()");
addDomHandler(this, LoadEvent.getType());
}
@@ -683,6 +711,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*/
public void setSuggestions(
Collection<FilterSelectSuggestion> suggestions) {
+ if (enableDebug) {
+ debug("VFS.SM: setSuggestions(" + suggestions + ")");
+ }
// Reset keyboard selection when contents is updated to avoid
// reusing old, invalid data
setKeyboardSelectedItem(null);
@@ -708,6 +739,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* is made or on a blur event.
*/
public void doSelectedItemAction() {
+ debug("VFS.SM: doSelectedItemAction()");
// do not send a value change event if null was and stays selected
final String enteredItemValue = tb.getText();
if (nullSelectionAllowed && "".equals(enteredItemValue)
@@ -737,6 +769,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Triggered after a selection has been made
*/
public void doPostFilterSelectedItemAction() {
+ debug("VFS.SM: doPostFilterSelectedItemAction()");
final MenuItem item = getSelectedItem();
final String enteredItemValue = tb.getText();
@@ -833,6 +866,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onLoad(LoadEvent event) {
+ debug("VFS.SM: onLoad()");
// Handle icon onload events to ensure shadow is resized
// correctly
delayedImageLoadExecutioner.trigger();
@@ -840,6 +874,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
public void selectFirstItem() {
+ debug("VFS.SM: selectFirstItem()");
MenuItem firstItem = getItems().get(0);
selectItem(firstItem);
}
@@ -853,6 +888,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
public void selectLastItem() {
+ debug("VFS.SM: selectLastItem()");
List<MenuItem> items = getItems();
MenuItem lastItem = items.get(items.size() - 1);
selectItem(lastItem);
@@ -1145,6 +1181,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Whether to send the options request immediately
*/
private void filterOptions(int page, String filter, boolean immediate) {
+ if (enableDebug) {
+ debug("VFS: filterOptions(" + page + ", " + filter + ", "
+ + immediate + ")");
+ }
if (filter.equals(lastFilter) && currentPage == page) {
if (!suggestionPopup.isAttached()) {
suggestionPopup.showSuggestions(currentSuggestions,
@@ -1171,10 +1211,12 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/** For internal use only. May be removed or replaced in the future. */
public void updateReadOnly() {
+ debug("VFS: updateReadOnly()");
tb.setReadOnly(readonly || !textInputEnabled);
}
public void setTextInputEnabled(boolean textInputEnabled) {
+ debug("VFS: setTextInputEnabled()");
// Always update styles as they might have been overwritten
if (textInputEnabled) {
removeStyleDependentName(STYLE_NO_INPUT);
@@ -1200,6 +1242,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* the text to set in the text box
*/
public void setTextboxText(final String text) {
+ if (enableDebug) {
+ debug("VFS: setTextboxText(" + text + ")");
+ }
tb.setText(text);
}
@@ -1208,6 +1253,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* in the text box if nothing has been entered.
*/
public void setPromptingOn() {
+ debug("VFS: setPromptingOn()");
if (!prompting) {
prompting = true;
addStyleDependentName(CLASSNAME_PROMPT);
@@ -1225,6 +1271,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* The text the text box should contain.
*/
public void setPromptingOff(String text) {
+ debug("VFS: setPromptingOff()");
setTextboxText(text);
if (prompting) {
prompting = false;
@@ -1239,6 +1286,10 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* The suggestion that just got selected.
*/
public void onSuggestionSelected(FilterSelectSuggestion suggestion) {
+ if (enableDebug) {
+ debug("VFS: onSuggestionSelected(" + suggestion.caption + ": "
+ + suggestion.key + ")");
+ }
updateSelectionWhenReponseIsReceived = false;
currentSuggestion = suggestion;
@@ -1334,7 +1385,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
if (enabled && !readonly) {
int keyCode = event.getNativeKeyCode();
- debug("key down: " + keyCode);
+ if (enableDebug) {
+ debug("VFS: key down: " + keyCode);
+ }
if (waitingForFilteringResponse
&& navigationKeyCodes.contains(keyCode)) {
/*
@@ -1342,18 +1395,25 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* waiting for a response. This avoids flickering, disappearing
* items, wrongly interpreted responses and more.
*/
- debug("Ignoring " + keyCode
- + " because we are waiting for a filtering response");
+ if (enableDebug) {
+ debug("Ignoring "
+ + keyCode
+ + " because we are waiting for a filtering response");
+ }
DOM.eventPreventDefault(DOM.eventGetCurrentEvent());
event.stopPropagation();
return;
}
if (suggestionPopup.isAttached()) {
- debug("Keycode " + keyCode + " target is popup");
+ if (enableDebug) {
+ debug("Keycode " + keyCode + " target is popup");
+ }
popupKeyDown(event);
} else {
- debug("Keycode " + keyCode + " target is text field");
+ if (enableDebug) {
+ debug("Keycode " + keyCode + " target is text field");
+ }
inputFieldKeyDown(event);
}
}
@@ -1372,6 +1432,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* The KeyDownEvent
*/
private void inputFieldKeyDown(KeyDownEvent event) {
+ if (enableDebug) {
+ debug("VFS: inputFieldKeyDown(" + event.getNativeKeyCode() + ")");
+ }
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_DOWN:
case KeyCodes.KEY_UP:
@@ -1414,6 +1477,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* The KeyDownEvent of the key
*/
private void popupKeyDown(KeyDownEvent event) {
+ if (enableDebug) {
+ debug("VFS: popupKeyDown(" + event.getNativeKeyCode() + ")");
+ }
// Propagation of handled events is stopped so other handlers such as
// shortcut key handlers do not also handle the same events.
switch (event.getNativeKeyCode()) {
@@ -1494,6 +1560,9 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onKeyUp(KeyUpEvent event) {
+ if (enableDebug) {
+ debug("VFS: onKeyUp(" + event.getNativeKeyCode() + ")");
+ }
if (enabled && !readonly) {
switch (event.getNativeKeyCode()) {
case KeyCodes.KEY_ENTER:
@@ -1521,6 +1590,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* Resets the Select to its initial state
*/
private void reset() {
+ debug("VFS: reset()");
if (currentSuggestion != null) {
String text = currentSuggestion.getReplacementString();
setPromptingOff(text);
@@ -1543,6 +1613,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onClick(ClickEvent event) {
+ debug("VFS: onClick()");
if (textInputEnabled
&& event.getNativeEvent().getEventTarget().cast() == tb
.getElement()) {
@@ -1569,6 +1640,29 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
/**
+ * Update minimum width for FilterSelect textarea based on input prompt and
+ * suggestions.
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public void updateSuggestionPopupMinWidth() {
+ // used only to calculate minimum width
+ String captions = Util.escapeHTML(inputPrompt);
+
+ for (FilterSelectSuggestion suggestion : currentSuggestions) {
+ // Collect captions so we can calculate minimum width for
+ // textarea
+ if (captions.length() > 0) {
+ captions += "|";
+ }
+ captions += Util.escapeHTML(suggestion.getReplacementString());
+ }
+
+ // Calculate minimum textarea width
+ suggestionPopupMinWidth = minWidth(captions);
+ }
+
+ /**
* Calculate minimum width for FilterSelect textarea.
* <p>
* For internal use only. May be removed or replaced in the future.
@@ -1610,6 +1704,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onFocus(FocusEvent event) {
+ debug("VFS: onFocus()");
/*
* When we disable a blur event in ie we need to refocus the textfield.
@@ -1648,6 +1743,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void onBlur(BlurEvent event) {
+ debug("VFS: onBlur()");
if (BrowserInfo.get().isIE() && preventNextBlurEventInIE) {
/*
@@ -1708,6 +1804,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
@Override
public void focus() {
+ debug("VFS: focus()");
focused = true;
if (prompting && !readonly) {
setPromptingOff("");
@@ -1807,6 +1904,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*/
if (BrowserInfo.get().isIE() && focused) {
preventNextBlurEventInIE = true;
+ debug("VFS: Going to prevent next blur event on IE");
}
}
}
diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java
index 0ed5bd57bd..38dfdba1b8 100644
--- a/client/src/com/vaadin/client/ui/VWindow.java
+++ b/client/src/com/vaadin/client/ui/VWindow.java
@@ -415,14 +415,6 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
@Override
public void hide() {
- if (vaadinModality) {
- hideModalityCurtain();
- }
- super.hide();
-
- // Remove window from windowOrder to avoid references being left
- // hanging.
- windowOrder.remove(this);
/*
* If the window has a RichTextArea and the RTA is focused at the time
@@ -439,20 +431,28 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
if (BrowserInfo.get().isIE8()) {
fixIE8FocusCaptureIssue();
}
+
+ if (vaadinModality) {
+ hideModalityCurtain();
+ }
+ super.hide();
+
+ // Remove window from windowOrder to avoid references being left
+ // hanging.
+ windowOrder.remove(this);
}
private void fixIE8FocusCaptureIssue() {
Element e = DOM.createInputText();
Style elemStyle = e.getStyle();
elemStyle.setPosition(Position.ABSOLUTE);
- elemStyle.setLeft(-10, Unit.PX);
+ elemStyle.setTop(-10, Unit.PX);
elemStyle.setWidth(0, Unit.PX);
elemStyle.setHeight(0, Unit.PX);
- Element rootPanel = RootPanel.getBodyElement();
- rootPanel.appendChild(e);
+ contentPanel.getElement().appendChild(e);
e.focus();
- rootPanel.removeChild(e);
+ contentPanel.getElement().removeChild(e);
}
/** For internal use only. May be removed or replaced in the future. */
diff --git a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java
index 98d2651849..e96d27032b 100644
--- a/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java
+++ b/client/src/com/vaadin/client/ui/combobox/ComboBoxConnector.java
@@ -20,7 +20,6 @@ import java.util.Iterator;
import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.Paintable;
import com.vaadin.client.UIDL;
-import com.vaadin.client.Util;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.ui.VFilterSelect;
@@ -124,9 +123,6 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
getWidget().totalMatches = 0;
}
- // used only to calculate minimum popup width
- String captions = Util.escapeHTML(getWidget().inputPrompt);
-
for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) {
final UIDL optionUidl = (UIDL) i.next();
final FilterSelectSuggestion suggestion = getWidget().new FilterSelectSuggestion(
@@ -152,12 +148,6 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
getWidget().currentSuggestion = suggestion;
getWidget().setSelectedItemIcon(suggestion.getIconUri());
}
-
- // Collect captions so we can calculate minimum width for textarea
- if (captions.length() > 0) {
- captions += "|";
- }
- captions += Util.escapeHTML(suggestion.getReplacementString());
}
if ((!getWidget().waitingForFilteringResponse || getWidget().popupOpenerClicked)
@@ -222,8 +212,8 @@ public class ComboBoxConnector extends AbstractFieldConnector implements
}
}
- // Calculate minumum textarea width
- getWidget().suggestionPopupMinWidth = getWidget().minWidth(captions);
+ // Calculate minimum textarea width
+ getWidget().updateSuggestionPopupMinWidth();
getWidget().popupOpenerClicked = false;
diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
index d8b0888936..b5a6262693 100644
--- a/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
+++ b/client/src/com/vaadin/client/ui/orderedlayout/VAbstractOrderedLayout.java
@@ -503,14 +503,10 @@ public class VAbstractOrderedLayout extends FlowPanel {
// TODO check caption position
if (vertical) {
int size = layoutManager.getOuterHeight(slot
- .getWidget().getElement())
- - layoutManager.getMarginHeight(slot
- .getWidget().getElement());
+ .getWidget().getElement());
if (slot.hasCaption()) {
size += layoutManager.getOuterHeight(slot
- .getCaptionElement())
- - layoutManager.getMarginHeight(slot
- .getCaptionElement());
+ .getCaptionElement());
}
if (size > 0) {
totalSize += size;
@@ -518,14 +514,10 @@ public class VAbstractOrderedLayout extends FlowPanel {
} else {
int max = -1;
max = layoutManager.getOuterWidth(slot.getWidget()
- .getElement())
- - layoutManager.getMarginWidth(slot
- .getWidget().getElement());
+ .getElement());
if (slot.hasCaption()) {
int max2 = layoutManager.getOuterWidth(slot
- .getCaptionElement())
- - layoutManager.getMarginWidth(slot
- .getCaptionElement());
+ .getCaptionElement());
max = Math.max(max, max2);
}
if (max > 0) {
diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java
index b383878f28..327ce78a6c 100644
--- a/server/src/com/vaadin/server/VaadinPortlet.java
+++ b/server/src/com/vaadin/server/VaadinPortlet.java
@@ -17,6 +17,7 @@ package com.vaadin.server;
import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;
@@ -40,7 +41,7 @@ import javax.portlet.ResourceResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
-import com.liferay.portal.kernel.util.PortalClassInvoker;
+import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.PropsUtil;
import com.vaadin.server.communication.PortletDummyRequestHandler;
import com.vaadin.server.communication.PortletUIInitHandler;
@@ -171,19 +172,75 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
return PropsUtil.get(name);
}
+ /**
+ * Simplified version of what Liferay PortalClassInvoker did. This is
+ * used because the API of PortalClassInvoker has changed in Liferay
+ * 6.2.
+ *
+ * This simply uses reflection with Liferay class loader. Parameters are
+ * Strings to avoid static dependencies and to load all classes with
+ * Liferay's own class loader. Only static utility methods are
+ * supported.
+ *
+ * This method is for internal use only and may change in future
+ * versions.
+ *
+ * @param className
+ * name of the Liferay class to call
+ * @param methodName
+ * name of the method to call
+ * @param parameterClassName
+ * name of the parameter class of the method
+ * @throws Exception
+ * @return return value of the invoked method
+ */
+ private static Object invokeStaticLiferayMethod(String className,
+ String methodName, Object argument, String parameterClassName)
+ throws Exception {
+ Thread currentThread = Thread.currentThread();
+
+ ClassLoader contextClassLoader = currentThread
+ .getContextClassLoader();
+
+ try {
+ // this should be available across all Liferay versions with no
+ // problematic static dependencies
+ ClassLoader portalClassLoader = PortalClassLoaderUtil
+ .getClassLoader();
+ // this is in case the class loading triggers code that
+ // explicitly
+ // uses current thread class loader
+ currentThread.setContextClassLoader(portalClassLoader);
+
+ Class<?> targetClass = portalClassLoader.loadClass(className);
+ Class<?> parameterClass = portalClassLoader
+ .loadClass(parameterClassName);
+ Method method = targetClass.getMethod(methodName,
+ parameterClass);
+
+ return method.invoke(null, new Object[] { argument });
+ } catch (InvocationTargetException ite) {
+ throw (Exception) ite.getCause();
+ } finally {
+ currentThread.setContextClassLoader(contextClassLoader);
+ }
+ }
+
private static HttpServletRequest getOriginalRequest(
PortletRequest request) {
try {
// httpRequest = PortalUtil.getHttpServletRequest(request);
- HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
- .invoke("com.liferay.portal.util.PortalUtil",
- "getHttpServletRequest", request);
+ HttpServletRequest httpRequest = (HttpServletRequest) invokeStaticLiferayMethod(
+ "com.liferay.portal.util.PortalUtil",
+ "getHttpServletRequest", request,
+ "javax.portlet.PortletRequest");
// httpRequest =
// PortalUtil.getOriginalServletRequest(httpRequest);
- httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
+ httpRequest = (HttpServletRequest) invokeStaticLiferayMethod(
"com.liferay.portal.util.PortalUtil",
- "getOriginalServletRequest", httpRequest);
+ "getOriginalServletRequest", httpRequest,
+ "javax.servlet.http.HttpServletRequest");
return httpRequest;
} catch (Exception e) {
throw new IllegalStateException("Liferay request not detected",
diff --git a/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html b/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html
new file mode 100644
index 0000000000..d0dec8ce40
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.html
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8068/" />
+<title>TextChangeListenerLosesFocus</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TextChangeListenerLosesFocus</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.textfield.TextChangeListenerLosesFocus?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>focus</td>
+ <td>test-textfield</td>
+ <td></td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>test-textfield</td>
+ <td>123</td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td>1000</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertValue</td>
+ <td>test-textfield</td>
+ <td>Updated by TextChangeListener</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>test-textfield</td>
+ <td>v-textfield-focus</td>
+</tr>
+<tr>
+ <td>focus</td>
+ <td>test-textarea</td>
+ <td></td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>test-textarea</td>
+ <td>123</td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td>1000</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertValue</td>
+ <td>test-textarea</td>
+ <td>Updated by TextChangeListener</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>test-textarea</td>
+ <td>v-textarea-focus</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java
index ad372bd5bc..070cd2834d 100644
--- a/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java
+++ b/uitest/src/com/vaadin/launcher/DevelopmentServerLauncher.java
@@ -22,9 +22,20 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
@@ -163,6 +174,25 @@ public class DevelopmentServerLauncher {
webappcontext.setWar(serverArgs.get("webroot"));
server.setHandler(webappcontext);
+ // --slowdown=/run/APP/PUBLISHED/*,/other/path/asd.jpg
+ // slows down specified paths
+ if (serverArgs.containsKey("slowdown")) {
+ String[] paths = serverArgs.get("slowdown").split(",");
+ for (String p : paths) {
+ System.out.println("Slowing down: " + p);
+ webappcontext.addFilter(SlowFilter.class, p, 1);
+ }
+ }
+ // --cache=/run/APP/PUBLISHED/*,/other/path/asd.jpg
+ // caches specified paths
+ if (serverArgs.containsKey("cache")) {
+ String[] paths = serverArgs.get("cache").split(",");
+ for (String p : paths) {
+ System.out.println("Enabling cache for: " + p);
+ webappcontext.addFilter(CacheFilter.class, p, 1);
+ }
+ }
+
try {
server.start();
@@ -243,4 +273,83 @@ public class DevelopmentServerLauncher {
return map;
}
+ /**
+ * Sleeps for 2-5 seconds when serving resources that matches given
+ * pathSpec. --slowdown=/run/APP/PUBLISHED/*,/other/path/asd.jpg
+ */
+ public static class SlowFilter implements Filter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ String path = ((HttpServletRequest) request).getPathInfo();
+ long delay = Math.round(Math.random() * 3000) + 2000;
+ System.out.println("Delaying " + path + " for " + delay);
+
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException e) {
+ System.out.println("Delay interrupted for " + path);
+ } finally {
+ System.out.println("Resuming " + path);
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ // TODO Auto-generated method stub
+ }
+
+ }
+
+ /**
+ * Adds "Expires" and "Cache-control" headers when serving resources that
+ * match given pathSpec, in order to cache resource for CACHE_MINUTES.
+ * --cache=/run/APP/PUBLISHED/*,/other/path/asd.jpg
+ */
+ public static class CacheFilter implements Filter {
+
+ private static final int CACHE_MINUTES = 1;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ String path = ((HttpServletRequest) request).getPathInfo();
+ System.out.println("Caching " + path + " for " + CACHE_MINUTES
+ + " minutes");
+
+ Calendar calendar = Calendar.getInstance();
+ calendar.add(Calendar.MINUTE, CACHE_MINUTES);
+
+ String expires = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z")
+ .format(calendar.getTime());
+
+ ((HttpServletResponse) response).setHeader("Expires", expires);
+ ((HttpServletResponse) response).setHeader("Cache-Control",
+ "max-age=" + (CACHE_MINUTES * 60));
+
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ // TODO Auto-generated method stub
+ }
+
+ }
+
}
diff --git a/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java b/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java
new file mode 100644
index 0000000000..2d2cf29e9e
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textarea/TextDisappearsOnBlur.java
@@ -0,0 +1,29 @@
+package com.vaadin.tests.components.textarea;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.TextArea;
+
+public class TextDisappearsOnBlur extends TestBase {
+
+ @Override
+ protected void setup() {
+ TextArea ta = new TextArea();
+ addComponent(ta);
+
+ // All three are required for the bug to manifest
+ ta.setMaxLength(50);
+ ta.setImmediate(true);
+ ta.setRequired(true);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Text disappears from TextArea in IE 6-8 when focus changes";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 11396;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java b/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java
new file mode 100644
index 0000000000..25ca46333a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textfield/TextChangeListenerLosesFocus.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 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.textfield;
+
+import com.vaadin.event.FieldEvents.TextChangeEvent;
+import com.vaadin.event.FieldEvents.TextChangeListener;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.tests.util.TestUtils;
+import com.vaadin.ui.AbstractTextField;
+import com.vaadin.ui.Field;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.TextField;
+
+public class TextChangeListenerLosesFocus extends TestBase {
+
+ private final TextChangeListener listener = new TextChangeListener() {
+ public void textChange(TextChangeEvent event) {
+ final String value = event.getText();
+ if (value.length() > 2) {
+ ((Field) event.getComponent())
+ .setValue("Updated by TextChangeListener");
+ }
+ }
+ };
+
+ @Override
+ protected void setup() {
+ TestUtils.injectCSS(getMainWindow(),
+ ".v-textfield-focus, .v-textarea-focus { "
+ + " background: #E8F0FF !important }");
+
+ AbstractTextField field = new TextField();
+ field.setDebugId("test-textfield");
+ field.setInputPrompt("Enter at least 3 characters");
+ field.addListener(listener);
+ addComponent(field);
+
+ field = new TextArea();
+ field.setDebugId("test-textarea");
+ field.setInputPrompt("Enter at least 3 characters");
+ field.addListener(listener);
+ addComponent(field);
+
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Updating a focused TextField overwrites the focus stylename";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 11623;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html
new file mode 100644
index 0000000000..3132bdd16d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.html
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8070/" />
+<title>MarginWithExpandRatio</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">MarginWithExpandRatio</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/MarginWithExpandRatio?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>no-overflow</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java
new file mode 100644
index 0000000000..f6ee26e86f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/layouts/MarginWithExpandRatio.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2013 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.layouts;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.util.TestUtils;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.VerticalLayout;
+
+public class MarginWithExpandRatio extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ TestUtils.injectCSS(this,
+ ".hugemargin { margin: 10px 20px !important; }");
+
+ HorizontalLayout hl = new HorizontalLayout();
+ addLayoutTest(hl);
+ hl.setExpandRatio(hl.getComponent(0), 1.0f);
+ hl.setExpandRatio(hl.getComponent(2), 0.5f);
+ VerticalLayout vl = new VerticalLayout();
+ addLayoutTest(vl);
+ vl.setExpandRatio(vl.getComponent(0), 1.0f);
+ vl.setExpandRatio(vl.getComponent(2), 0.5f);
+
+ GridLayout gl = new GridLayout(2, 1);
+ addLayoutTest(gl);
+ gl.setColumnExpandRatio(0, 1.0f);
+ gl.setRowExpandRatio(0, 1.0f);
+ gl.setColumnExpandRatio(1, 0.5f);
+ gl.setRowExpandRatio(1, 0.5f);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Layout content overflows if CSS margin used with expand ratio";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 11553;
+ }
+
+ private void addLayoutTest(Layout l) {
+ l.setSizeFull();
+
+ Label lbl = new Label("First (expand ratio 1)");
+ lbl.setSizeUndefined();
+ l.addComponent(lbl);
+
+ lbl = new Label("Second (margin 10px)");
+ lbl.setSizeUndefined();
+ lbl.addStyleName("hugemargin");
+ l.addComponent(lbl);
+
+ lbl = new Label("Third (margin+xr)");
+ lbl.setSizeUndefined();
+ lbl.addStyleName("hugemargin");
+ l.addComponent(lbl);
+
+ Panel p = new Panel(l.getClass().getSimpleName(), l);
+ p.setWidth("600px");
+ p.setHeight("200px");
+ addComponent(p);
+ }
+}
diff --git a/uitest/test.xml b/uitest/test.xml
index 5ff39c425d..8228bd9d70 100644
--- a/uitest/test.xml
+++ b/uitest/test.xml
@@ -182,6 +182,7 @@
<sequential>
<ant antfile="${test.xml.dir}/vaadin-server.xml" target="wait-for-startup" />
<antcall inheritall="true" inheritrefs="true" target="run-and-clean-up" />
+ <echo message="All TestBench tests have been run" />
</sequential>
</parallel>
</target>
diff --git a/uitest/vaadin-server.xml b/uitest/vaadin-server.xml
index e02fab8564..5741d78525 100644
--- a/uitest/vaadin-server.xml
+++ b/uitest/vaadin-server.xml
@@ -8,7 +8,7 @@
<ivy:resolve file="${dir}/ivy.xml" />
<ivy:cachepath pathid="classpath.jetty" conf="jetty-run" />
- <java classname="org.mortbay.jetty.runner.Runner" fork="yes">
+ <java classname="org.mortbay.jetty.runner.Runner" fork="yes" output="${vaadin.basedir}/result/jetty.java.out" resultproperty="resultCode">
<arg value="--port" />
<arg value="8888" />
<arg value="--out" />
@@ -19,6 +19,7 @@
<classpath refid="classpath.jetty" />
<jvmarg value="-ea" />
</java>
+ <echo message="Jetty process ended with result code ${resultCode}" />
</target>