@@ -481,11 +481,11 @@ | |||
</p> | |||
<ul> | |||
<li>Mozilla Firefox 3-6</li> | |||
<li>Mozilla Firefox 3-8</li> | |||
<li>Internet Explorer 6-9</li> | |||
<li>Safari 4-5</li> | |||
<li>Opera 10-11</li> | |||
<li>Google Chrome 13</li> | |||
<li>Google Chrome 13-15</li> | |||
</ul> | |||
<h2 id="vaadinontheweb">Vaadin on the Web</h2> |
@@ -7,8 +7,10 @@ package com.vaadin.terminal.gwt.client.ui; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import com.google.gwt.core.client.Scheduler; | |||
import com.google.gwt.core.client.Scheduler.ScheduledCommand; | |||
@@ -49,6 +51,7 @@ import com.vaadin.terminal.gwt.client.Focusable; | |||
import com.vaadin.terminal.gwt.client.Paintable; | |||
import com.vaadin.terminal.gwt.client.UIDL; | |||
import com.vaadin.terminal.gwt.client.Util; | |||
import com.vaadin.terminal.gwt.client.VConsole; | |||
import com.vaadin.terminal.gwt.client.VTooltip; | |||
/** | |||
@@ -56,6 +59,7 @@ import com.vaadin.terminal.gwt.client.VTooltip; | |||
* | |||
* TODO needs major refactoring (to be extensible etc) | |||
*/ | |||
@SuppressWarnings("deprecation") | |||
public class VFilterSelect extends Composite implements Paintable, Field, | |||
KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, | |||
Focusable { | |||
@@ -96,7 +100,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
sb.append(Util.escapeAttribute(iconUri)); | |||
sb.append("\" alt=\"\" class=\"v-icon\" />"); | |||
} | |||
sb.append("<span>" + Util.escapeHTML(caption) + "</span>"); | |||
String content; | |||
if ("".equals(caption)) { | |||
// Ensure that empty options use the same height as other | |||
// options and are not collapsed (#7506) | |||
content = " "; | |||
} else { | |||
content = Util.escapeHTML(caption); | |||
} | |||
sb.append("<span>" + content + "</span>"); | |||
return sb.toString(); | |||
} | |||
@@ -286,7 +298,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
.getText().length() - lastFilter.length()); | |||
} else if (hasNextPage()) { | |||
lastIndex = index - 1; // save for paging | |||
selectPopupItemWhenResponseIsReceived = Select.FIRST; | |||
filterOptions(currentPage + 1, lastFilter); | |||
} | |||
} | |||
@@ -305,7 +317,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
.getText().length() - lastFilter.length()); | |||
} else if (index == -1) { | |||
if (currentPage > 0) { | |||
lastIndex = index + 1; // save for paging | |||
selectPopupItemWhenResponseIsReceived = Select.LAST; | |||
filterOptions(currentPage - 1, lastFilter); | |||
} | |||
} else { | |||
@@ -330,7 +342,20 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
@Override | |||
public void run() { | |||
if (pagesToScroll != 0) { | |||
filterOptions(currentPage + pagesToScroll, lastFilter); | |||
if (!waitingForFilteringResponse) { | |||
/* | |||
* Avoid scrolling while we are waiting for a response | |||
* because otherwise the waiting flag will be reset in | |||
* the first response and the second response will be | |||
* ignored, causing an empty popup... | |||
* | |||
* As long as the scrolling delay is suitable | |||
* double/triple clicks will work by scrolling two or | |||
* three pages at a time and this should not be a | |||
* problem. | |||
*/ | |||
filterOptions(currentPage + pagesToScroll, lastFilter); | |||
} | |||
pagesToScroll = 0; | |||
} | |||
} | |||
@@ -339,7 +364,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
if (currentPage + pagesToScroll > 0) { | |||
pagesToScroll--; | |||
cancel(); | |||
schedule(100); | |||
schedule(200); | |||
} | |||
} | |||
@@ -348,7 +373,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
* pageLength) { | |||
pagesToScroll++; | |||
cancel(); | |||
schedule(100); | |||
schedule(200); | |||
} | |||
} | |||
} | |||
@@ -538,6 +563,13 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
public class SuggestionMenu extends MenuBar implements SubPartAware, | |||
LoadHandler { | |||
/** | |||
* Tracks the item that is currently selected using the keyboard. This | |||
* is need only because mouseover changes the selection and we do not | |||
* want to use that selection when pressing enter to select the item. | |||
*/ | |||
private MenuItem keyboardSelectedItem; | |||
private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( | |||
100, new ScheduledCommand() { | |||
@@ -584,6 +616,10 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
*/ | |||
public void setSuggestions( | |||
Collection<FilterSelectSuggestion> suggestions) { | |||
// Reset keyboard selection when contents is updated to avoid | |||
// reusing old, invalid data | |||
setKeyboardSelectedItem(null); | |||
clearItems(); | |||
final Iterator<FilterSelectSuggestion> it = suggestions.iterator(); | |||
while (it.hasNext()) { | |||
@@ -623,8 +659,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
return; | |||
} | |||
selecting = filtering; | |||
if (!filtering) { | |||
updateSelectionWhenReponseIsReceived = waitingForFilteringResponse; | |||
if (!waitingForFilteringResponse) { | |||
doPostFilterSelectedItemAction(); | |||
} | |||
} | |||
@@ -636,7 +672,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
final MenuItem item = getSelectedItem(); | |||
final String enteredItemValue = tb.getText(); | |||
selecting = false; | |||
updateSelectionWhenReponseIsReceived = false; | |||
// check for exact match in menu | |||
int p = getItems().size(); | |||
@@ -737,6 +773,25 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
delayedImageLoadExecutioner.trigger(); | |||
} | |||
public void selectFirstItem() { | |||
MenuItem firstItem = getItems().get(0); | |||
selectItem(firstItem); | |||
} | |||
private MenuItem getKeyboardSelectedItem() { | |||
return keyboardSelectedItem; | |||
} | |||
private void setKeyboardSelectedItem(MenuItem firstItem) { | |||
keyboardSelectedItem = firstItem; | |||
} | |||
public void selectLastItem() { | |||
List<MenuItem> items = getItems(); | |||
MenuItem lastItem = items.get(items.size() - 1); | |||
selectItem(lastItem); | |||
} | |||
} | |||
public static final int FILTERINGMODE_OFF = 0; | |||
@@ -748,6 +803,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
protected int pageLength = 10; | |||
private boolean enableDebug = false; | |||
private final FlowPanel panel = new FlowPanel(); | |||
/** | |||
@@ -821,19 +878,24 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
* A collection of available suggestions (options) as received from the | |||
* server. | |||
*/ | |||
private final Collection<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); | |||
private final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); | |||
private boolean immediate; | |||
private String selectedOptionKey; | |||
private boolean filtering = false; | |||
private boolean selecting = false; | |||
private boolean tabPressed = false; | |||
private boolean waitingForFilteringResponse = false; | |||
private boolean updateSelectionWhenReponseIsReceived = false; | |||
private boolean tabPressedWhenPopupOpen = false; | |||
private boolean initDone = false; | |||
private String lastFilter = ""; | |||
private int lastIndex = -1; // last selected index when using arrows | |||
private enum Select { | |||
NONE, FIRST, LAST | |||
}; | |||
private Select selectPopupItemWhenResponseIsReceived = Select.NONE; | |||
/** | |||
* The current suggestion selected from the dropdown. This is one of the | |||
@@ -968,7 +1030,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
} | |||
} | |||
filtering = true; | |||
waitingForFilteringResponse = true; | |||
client.updateVariable(paintableId, "filter", filter, false); | |||
client.updateVariable(paintableId, "page", page, true); | |||
lastFilter = filter; | |||
@@ -1032,14 +1094,13 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
inputPrompt = ""; | |||
} | |||
suggestionPopup.setPagingEnabled(true); | |||
suggestionPopup.updateStyleNames(uidl); | |||
allowNewItem = uidl.hasAttribute("allownewitem"); | |||
lastNewItemString = null; | |||
currentSuggestions.clear(); | |||
if (!filtering) { | |||
if (!waitingForFilteringResponse) { | |||
/* | |||
* Clear the current suggestions as the server response always | |||
* includes the new ones. Exception is when filtering, then we need | |||
@@ -1059,6 +1120,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
final UIDL options = uidl.getChildUIDL(0); | |||
if (uidl.hasAttribute("totalMatches")) { | |||
totalMatches = uidl.getIntAttribute("totalMatches"); | |||
} else { | |||
totalMatches = 0; | |||
} | |||
// used only to calculate minimum popup width | |||
@@ -1070,7 +1133,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
optionUidl); | |||
currentSuggestions.add(suggestion); | |||
if (optionUidl.hasAttribute("selected")) { | |||
if (!filtering || popupOpenerClicked) { | |||
if (!waitingForFilteringResponse || popupOpenerClicked) { | |||
String newSelectedOptionKey = Integer.toString(suggestion | |||
.getOptionKey()); | |||
if (!newSelectedOptionKey.equals(selectedOptionKey) | |||
@@ -1094,10 +1157,11 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
captions += Util.escapeHTML(suggestion.getReplacementString()); | |||
} | |||
if ((!filtering || popupOpenerClicked) && uidl.hasVariable("selected") | |||
if ((!waitingForFilteringResponse || popupOpenerClicked) | |||
&& uidl.hasVariable("selected") | |||
&& uidl.getStringArrayVariable("selected").length == 0) { | |||
// select nulled | |||
if (!filtering || !popupOpenerClicked) { | |||
if (!waitingForFilteringResponse || !popupOpenerClicked) { | |||
if (!focused) { | |||
/* | |||
* client.updateComponent overwrites all styles so we must | |||
@@ -1115,41 +1179,35 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
selectedOptionKey = null; | |||
} | |||
if (filtering | |||
if (waitingForFilteringResponse | |||
&& lastFilter.toLowerCase().equals( | |||
uidl.getStringVariable("filter"))) { | |||
suggestionPopup.showSuggestions(currentSuggestions, currentPage, | |||
totalMatches); | |||
filtering = false; | |||
if (!popupOpenerClicked && lastIndex != -1) { | |||
waitingForFilteringResponse = false; | |||
if (!popupOpenerClicked | |||
&& selectPopupItemWhenResponseIsReceived != Select.NONE) { | |||
// we're paging w/ arrows | |||
MenuItem activeMenuItem; | |||
if (lastIndex == 0) { | |||
// going up, select last item | |||
int lastItem = pageLength - 1; | |||
List<MenuItem> items = suggestionPopup.menu.getItems(); | |||
/* | |||
* The first page can contain less than 10 items if the null | |||
* selection item is filtered away | |||
*/ | |||
if (lastItem >= items.size()) { | |||
lastItem = items.size() - 1; | |||
} | |||
activeMenuItem = items.get(lastItem); | |||
suggestionPopup.menu.selectItem(activeMenuItem); | |||
if (selectPopupItemWhenResponseIsReceived == Select.LAST) { | |||
suggestionPopup.menu.selectLastItem(); | |||
} else { | |||
// going down, select first item | |||
activeMenuItem = suggestionPopup.menu.getItems().get(0); | |||
suggestionPopup.menu.selectItem(activeMenuItem); | |||
suggestionPopup.menu.selectFirstItem(); | |||
} | |||
// This is used for paging so we update the keyboard selection | |||
// variable as well. | |||
MenuItem activeMenuItem = suggestionPopup.menu | |||
.getSelectedItem(); | |||
suggestionPopup.menu.setKeyboardSelectedItem(activeMenuItem); | |||
// Update text field to contain the correct text | |||
setTextboxText(activeMenuItem.getText()); | |||
tb.setSelectionRange(lastFilter.length(), activeMenuItem | |||
.getText().length() - lastFilter.length()); | |||
lastIndex = -1; // reset | |||
selectPopupItemWhenResponseIsReceived = Select.NONE; // reset | |||
} | |||
if (selecting) { | |||
if (updateSelectionWhenReponseIsReceived) { | |||
suggestionPopup.menu.doPostFilterSelectedItemAction(); | |||
} | |||
} | |||
@@ -1261,7 +1319,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
* The suggestion that just got selected. | |||
*/ | |||
public void onSuggestionSelected(FilterSelectSuggestion suggestion) { | |||
selecting = false; | |||
updateSelectionWhenReponseIsReceived = false; | |||
currentSuggestion = suggestion; | |||
String newKey; | |||
@@ -1329,6 +1387,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
marginTop + "px"); | |||
} | |||
private static Set<Integer> navigationKeyCodes = new HashSet<Integer>(); | |||
static { | |||
navigationKeyCodes.add(KeyCodes.KEY_DOWN); | |||
navigationKeyCodes.add(KeyCodes.KEY_UP); | |||
navigationKeyCodes.add(KeyCodes.KEY_PAGEDOWN); | |||
navigationKeyCodes.add(KeyCodes.KEY_PAGEUP); | |||
navigationKeyCodes.add(KeyCodes.KEY_ENTER); | |||
} | |||
/* | |||
* (non-Javadoc) | |||
* | |||
@@ -1338,34 +1405,39 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
*/ | |||
public void onKeyDown(KeyDownEvent event) { | |||
if (enabled && !readonly) { | |||
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { | |||
// Same reaction to enter no matter on whether the popup is open | |||
if (suggestionPopup.isAttached()) { | |||
filterOptions(currentPage); | |||
} else if (currentSuggestion != null | |||
&& tb.getText().equals( | |||
currentSuggestion.getReplacementString())) { | |||
// Retain behavior from #6686 by returning without stopping | |||
// propagation if there's nothing to do | |||
return; | |||
} | |||
if (currentSuggestions.size() == 1 && !allowNewItem) { | |||
// If there is only one suggestion, select that | |||
suggestionPopup.menu.selectItem(suggestionPopup.menu | |||
.getItems().get(0)); | |||
} | |||
suggestionPopup.menu.doSelectedItemAction(); | |||
int keyCode = event.getNativeKeyCode(); | |||
debug("key down: " + keyCode); | |||
if (waitingForFilteringResponse | |||
&& navigationKeyCodes.contains(keyCode)) { | |||
/* | |||
* Keyboard navigation events should not be handled while we are | |||
* 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"); | |||
DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); | |||
event.stopPropagation(); | |||
return; | |||
} else if (suggestionPopup.isAttached()) { | |||
} | |||
if (suggestionPopup.isAttached()) { | |||
debug("Keycode " + keyCode + " target is popup"); | |||
popupKeyDown(event); | |||
} else { | |||
debug("Keycode " + keyCode + " target is text field"); | |||
inputFieldKeyDown(event); | |||
} | |||
} | |||
} | |||
private void debug(String string) { | |||
if (enableDebug) { | |||
VConsole.error(string); | |||
} | |||
} | |||
/** | |||
* Triggered when a key is pressed in the text box | |||
* | |||
@@ -1378,17 +1450,31 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
case KeyCodes.KEY_UP: | |||
case KeyCodes.KEY_PAGEDOWN: | |||
case KeyCodes.KEY_PAGEUP: | |||
if (!suggestionPopup.isAttached()) { | |||
// open popup as from gadget | |||
filterOptions(-1, ""); | |||
lastFilter = ""; | |||
tb.selectAll(); | |||
} | |||
// open popup as from gadget | |||
filterOptions(-1, ""); | |||
lastFilter = ""; | |||
tb.selectAll(); | |||
break; | |||
case KeyCodes.KEY_TAB: | |||
if (suggestionPopup.isAttached()) { | |||
filterOptions(currentPage, tb.getText()); | |||
case KeyCodes.KEY_ENTER: | |||
/* | |||
* This only handles the case when new items is allowed, a text is | |||
* entered, the popup opener button is clicked to close the popup | |||
* and enter is then pressed (see #7560). | |||
*/ | |||
if (!allowNewItem) { | |||
return; | |||
} | |||
if (currentSuggestion != null | |||
&& tb.getText().equals( | |||
currentSuggestion.getReplacementString())) { | |||
// Retain behavior from #6686 by returning without stopping | |||
// propagation if there's nothing to do | |||
return; | |||
} | |||
suggestionPopup.menu.doSelectedItemAction(); | |||
event.stopPropagation(); | |||
break; | |||
} | |||
@@ -1406,11 +1492,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
switch (event.getNativeKeyCode()) { | |||
case KeyCodes.KEY_DOWN: | |||
suggestionPopup.selectNextItem(); | |||
suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu | |||
.getSelectedItem()); | |||
DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); | |||
event.stopPropagation(); | |||
break; | |||
case KeyCodes.KEY_UP: | |||
suggestionPopup.selectPrevItem(); | |||
suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu | |||
.getSelectedItem()); | |||
DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); | |||
event.stopPropagation(); | |||
break; | |||
@@ -1427,12 +1517,43 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
event.stopPropagation(); | |||
break; | |||
case KeyCodes.KEY_TAB: | |||
if (suggestionPopup.isAttached()) { | |||
tabPressed = true; | |||
filterOptions(currentPage); | |||
} | |||
tabPressedWhenPopupOpen = true; | |||
filterOptions(currentPage); | |||
// onBlur() takes care of the rest | |||
break; | |||
case KeyCodes.KEY_ESCAPE: | |||
reset(); | |||
event.stopPropagation(); | |||
break; | |||
case KeyCodes.KEY_ENTER: | |||
if (suggestionPopup.menu.getKeyboardSelectedItem() == null) { | |||
/* | |||
* Nothing selected using up/down. Happens e.g. when entering a | |||
* text (causes popup to open) and then pressing enter. | |||
*/ | |||
if (!allowNewItem) { | |||
/* | |||
* New items are not allowed: If there is only one | |||
* suggestion, select that. Otherwise do nothing. | |||
*/ | |||
if (currentSuggestions.size() == 1) { | |||
onSuggestionSelected(currentSuggestions.get(0)); | |||
} | |||
} else { | |||
// Handle addition of new items. | |||
suggestionPopup.menu.doSelectedItemAction(); | |||
} | |||
} else { | |||
/* | |||
* Get the suggestion that was navigated to using up/down. | |||
*/ | |||
currentSuggestion = ((FilterSelectSuggestion) suggestionPopup.menu | |||
.getKeyboardSelectedItem().getCommand()); | |||
onSuggestionSelected(currentSuggestion); | |||
} | |||
event.stopPropagation(); | |||
break; | |||
} | |||
} | |||
@@ -1455,10 +1576,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
case KeyCodes.KEY_UP: | |||
case KeyCodes.KEY_PAGEDOWN: | |||
case KeyCodes.KEY_PAGEUP: | |||
; // NOP | |||
break; | |||
case KeyCodes.KEY_ESCAPE: | |||
reset(); | |||
; // NOP | |||
break; | |||
default: | |||
if (textInputEnabled) { | |||
@@ -1617,8 +1736,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, | |||
focused = false; | |||
if (!readonly) { | |||
// much of the TAB handling takes place here | |||
if (tabPressed) { | |||
tabPressed = false; | |||
if (tabPressedWhenPopupOpen) { | |||
tabPressedWhenPopupOpen = false; | |||
suggestionPopup.menu.doSelectedItemAction(); | |||
suggestionPopup.hide(); | |||
} else if (!suggestionPopup.isAttached() |
@@ -148,7 +148,7 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, | |||
} | |||
// Adds the required attribute | |||
if (isRequired()) { | |||
if (!isReadOnly() && isRequired()) { | |||
target.addAttribute("required", true); | |||
} | |||
@@ -0,0 +1,62 @@ | |||
<?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="" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxSlow?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>92,19</td> | |||
</tr> | |||
<tr> | |||
<td>enterCharacter</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>1</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>filter-no-match</td> | |||
</tr> | |||
<tr> | |||
<td>enterCharacter</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>Item 12</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>filter-11-matches-paging</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>filter-11-matches-page-2</td> | |||
</tr> | |||
<tr> | |||
<td>enterCharacter</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>Item 100</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>filter-2-matches-no-paging</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,112 @@ | |||
<?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="" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxIdenticalItems?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>66,8</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>enter</td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> | |||
<td>1. Item one-1 selected</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>enter</td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> | |||
<td>2. Item one-2 selected</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>down</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>enter</td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> | |||
<td>3. Item two selected</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>up</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>up</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>up</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> | |||
<td>enter</td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> | |||
<td>4. Item one-1 selected</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,54 @@ | |||
package com.vaadin.tests.components.combobox; | |||
import com.vaadin.data.Item; | |||
import com.vaadin.data.Property; | |||
import com.vaadin.data.Property.ValueChangeEvent; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.tests.util.Log; | |||
import com.vaadin.ui.ComboBox; | |||
public class ComboBoxIdenticalItems extends TestBase { | |||
private Log log = new Log(5); | |||
@Override | |||
public void setup() { | |||
final ComboBox select = new ComboBox("ComboBox"); | |||
select.addContainerProperty("caption", String.class, null); | |||
Item item = select.addItem("one-1"); | |||
item.getItemProperty("caption").setValue("One"); | |||
item = select.addItem("one-2"); | |||
item.getItemProperty("caption").setValue("One"); | |||
item = select.addItem("two"); | |||
item.getItemProperty("caption").setValue("Two"); | |||
select.setItemCaptionPropertyId("caption"); | |||
select.setNullSelectionAllowed(false); | |||
select.setImmediate(true); | |||
select.addListener(new Property.ValueChangeListener() { | |||
private static final long serialVersionUID = -7932700771673919620L; | |||
public void valueChange(ValueChangeEvent event) { | |||
log.log("Item " + select.getValue() + " selected"); | |||
} | |||
}); | |||
addComponent(log); | |||
addComponent(select); | |||
} | |||
@Override | |||
protected String getDescription() { | |||
return "Keyboard selecting of a value is broken in combobox if two " | |||
+ "items have the same caption. The first item's id is \"One-1\" " | |||
+ "while the second one is \"One-2\". Selecting with mouse works " | |||
+ "as expected but selecting with keyboard always returns the " | |||
+ "object \"One-1\"."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
// TODO Auto-generated method stub | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?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="" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxInPopup?restartApplication</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> | |||
<td>12,13</td> | |||
</tr> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> | |||
<td>Yes</td> | |||
</tr> | |||
<tr> | |||
<td>pressSpecialKey</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> | |||
<td>esc</td> | |||
</tr> | |||
<!--ensure the sub window is still open but the popup is not--> | |||
<tr> | |||
<td>assertText</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> | |||
<td>A combo box</td> | |||
</tr> | |||
<tr> | |||
<td>assertElementNotPresent</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> | |||
<td></td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,50 @@ | |||
package com.vaadin.tests.components.combobox; | |||
import com.vaadin.event.ShortcutAction.KeyCode; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.ui.Button; | |||
import com.vaadin.ui.Button.ClickEvent; | |||
import com.vaadin.ui.ComboBox; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.Window; | |||
public class ComboBoxInPopup extends TestBase { | |||
@Override | |||
protected void setup() { | |||
final Window w = new Window(); | |||
w.getContent().setSizeUndefined(); | |||
w.addComponent(createComboBox()); | |||
Button close = new Button("Close window", new Button.ClickListener() { | |||
public void buttonClick(ClickEvent event) { | |||
w.getParent().removeWindow(w); | |||
} | |||
}); | |||
close.setClickShortcut(KeyCode.ESCAPE, null); | |||
w.addComponent(close); | |||
getLayout().getWindow().addWindow(w); | |||
} | |||
private Component createComboBox() { | |||
ComboBox cb = new ComboBox("A combo box"); | |||
cb.addItem("Yes"); | |||
cb.addItem("No"); | |||
cb.addItem("Maybe"); | |||
return cb; | |||
} | |||
@Override | |||
protected String getDescription() { | |||
return "Escape is a shortcut for the close button. Pressing escape when the popup is open should cause only the popup to close, not the window."; | |||
} | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 6978; | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
<?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://arturwin.office.itmill.com:8888/" /> | |||
<title>New Test</title> | |||
</head> | |||
<body> | |||
<table cellpadding="1" cellspacing="1" border="1"> | |||
<thead> | |||
<tr><td rowspan="1" colspan="3">New Test</td></tr> | |||
</thead><tbody> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxNavigation?restartApplication&theme=chameleon</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> | |||
<td>5,9</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>combobox-with-null-item-chameleon</td> | |||
</tr> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxNavigation?restartApplication&theme=runo</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> | |||
<td>5,9</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>combobox-with-null-item-runo</td> | |||
</tr> | |||
<tr> | |||
<td>open</td> | |||
<td>/run/com.vaadin.tests.components.combobox.ComboBoxNavigation?restartApplication&theme=reindeer</td> | |||
<td></td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> | |||
<td>5,9</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>combobox-with-null-item-reindeer</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -0,0 +1,55 @@ | |||
package com.vaadin.tests.components.combobox; | |||
import java.util.Map; | |||
import com.vaadin.data.Property.ValueChangeEvent; | |||
import com.vaadin.data.Property.ValueChangeListener; | |||
import com.vaadin.tests.components.TestBase; | |||
import com.vaadin.tests.util.Log; | |||
import com.vaadin.ui.ComboBox; | |||
public class ComboBoxSlow extends TestBase { | |||
private Log log = new Log(5); | |||
@Override | |||
protected Integer getTicketNumber() { | |||
return 7949; | |||
} | |||
@Override | |||
protected String getDescription() { | |||
return "The ComboBox artificially introduces a server delay to more easily spot problems"; | |||
} | |||
public class SlowComboBox extends ComboBox { | |||
@Override | |||
public void changeVariables(Object source, Map<String, Object> variables) { | |||
try { | |||
Thread.sleep(1000); | |||
} catch (InterruptedException e) { | |||
// TODO Auto-generated catch block | |||
e.printStackTrace(); | |||
} | |||
super.changeVariables(source, variables); | |||
} | |||
} | |||
@Override | |||
protected void setup() { | |||
addComponent(log); | |||
final SlowComboBox cb = new SlowComboBox(); | |||
cb.setImmediate(true); | |||
for (int i = 0; i <= 1000; i++) { | |||
cb.addItem("Item " + i); | |||
} | |||
cb.addListener(new ValueChangeListener() { | |||
public void valueChange(ValueChangeEvent event) { | |||
log.log("Value changed to " + cb.getValue()); | |||
} | |||
}); | |||
addComponent(cb); | |||
} | |||
} |
@@ -250,30 +250,39 @@ | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Readonly/domChild[0]</td> | |||
<td>26,10</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Required/domChild[0]</td> | |||
<td>12,-8</td> | |||
</tr> | |||
<tr> | |||
<td>waitForVaadin</td> | |||
<td></td> | |||
<td></td> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Error indicators/domChild[0]</td> | |||
<td>7,-8</td> | |||
</tr> | |||
<tr> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>error</td> | |||
<td>readonly-required</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Readonly/domChild[0]</td> | |||
<td>26,10</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Required/domChild[0]</td> | |||
<td>3,-7</td> | |||
</tr> | |||
<tr> | |||
<td>mouseClick</td> | |||
<td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Error indicators/domChild[0]</td> | |||
<td>67,8</td> | |||
<td>7,-8</td> | |||
</tr> | |||
<tr> | |||
<td>waitForVaadin</td> | |||
<td></td> | |||
<td>screenCapture</td> | |||
<td></td> | |||
<td>error</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |
@@ -22,7 +22,7 @@ | |||
<td>6,10</td> | |||
</tr> | |||
<tr> | |||
<td>type</td> | |||
<td>enterCharacter</td> | |||
<td>vaadin=runcomvaadintestscomponentsdatefieldDateFieldTimezone::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[0]</td> | |||
<td>Europe/Helsinki (Eastern European Time)</td> | |||
</tr> | |||
@@ -51,7 +51,6 @@ | |||
<td>vaadin=runcomvaadintestscomponentsdatefieldDateFieldTimezone::PID_SLog_row_0</td> | |||
<td>2. Date changed to 12/31/09 11:00:00 PM UTC</td> | |||
</tr> | |||
</tbody></table> | |||
</body> | |||
</html> |