outline: 5px auto -webkit-focus-ring-color;
outline-offset: -4px;
}
-
+.i-filterselect-prompt .i-filterselect-input {
+ /* input prompt active, i.e empty select */
+ color: #999;
+ font-style: italic;
+}
.i-filterselect-button {
float: right;
width: 25px;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -4px;
}
-
+.i-filterselect-prompt .i-filterselect-input {
+ /* input prompt active, i.e empty select */
+ color: #999;
+ font-style: italic;
+}
.i-filterselect-button {
float: right;
width: 25px;
border-color: #5daee8;
}
+input.i-textfield-prompt,
+textarea.i-textarea-prompt {
+ color: #999;
+ font-style: italic;
+}
+
.i-textfield.i-readonly,
.i-textarea.i-readonly {
background: transparent;
border: none;
}
-
.i-richtextarea {
border: 1px solid #b6b6b6;
overflow: hidden;
.i-window-footer {
height: 8px;
margin-left: 9px;
- background: transparent url(window/img/bottom-right.png) no-repeat right top;
- /* IE7 bug fix */
+ background: transparent url(window/img/bottom-right.png) no-repeat right top;
+}
+.i-ie7 .i-window-footer {
position:relative;
}
border-color: #5daee8;
}
+input.i-textfield-prompt,
+textarea.i-textarea-prompt {
+ color: #999;
+ font-style: italic;
+}
+
.i-textfield.i-readonly,
.i-textarea.i-readonly {
background: transparent;
border: none;
}
-
.i-richtextarea {
border: 1px solid #b6b6b6;
overflow: hidden;
import com.itmill.toolkit.demo.sampler.features.panels.PanelBasic;
import com.itmill.toolkit.demo.sampler.features.panels.PanelLight;
import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxContains;
+import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxInputPrompt;
import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxNewItems;
import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxPlain;
import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxStartsWith;
import com.itmill.toolkit.demo.sampler.features.text.LabelRich;
import com.itmill.toolkit.demo.sampler.features.text.RichTextEditor;
import com.itmill.toolkit.demo.sampler.features.text.TextArea;
+import com.itmill.toolkit.demo.sampler.features.text.TextFieldInputPrompt;
import com.itmill.toolkit.demo.sampler.features.text.TextFieldSecret;
import com.itmill.toolkit.demo.sampler.features.text.TextFieldSingle;
import com.itmill.toolkit.demo.sampler.features.trees.TreeActions;
new TwinColumnSelect(), //
new NativeSelection(), //
new ComboBoxPlain(), //
+ new ComboBoxInputPrompt(), //
new ComboBoxStartsWith(), //
new ComboBoxContains(), //
new ComboBoxNewItems(), //
//
new TextFieldSingle(), //
new TextFieldSecret(), //
+ new TextFieldInputPrompt(), //
new TextArea(), //
new RichTextEditor(), //
});
--- /dev/null
+package com.itmill.toolkit.demo.sampler.features.selects;\r
+\r
+import com.itmill.toolkit.demo.sampler.APIResource;\r
+import com.itmill.toolkit.demo.sampler.Feature;\r
+import com.itmill.toolkit.demo.sampler.NamedExternalResource;\r
+import com.itmill.toolkit.demo.sampler.features.text.TextFieldInputPrompt;\r
+import com.itmill.toolkit.ui.ComboBox;\r
+\r
+public class ComboBoxInputPrompt extends Feature {\r
+ @Override\r
+ public String getName() {\r
+ return "Combobox with input prompt";\r
+ }\r
+\r
+ @Override\r
+ public String getDescription() {\r
+ return "ComboBox is a drop-down selection component with single item selection."\r
+ + " It can have an <i>input prompt</i> - a textual hint that is shown within"\r
+ + " the select when no value is selected.<br/>"\r
+ + " You can use an input prompt instead of a caption to save"\r
+ + " space, but only do so if the function of the ComboBox is"\r
+ + " still clear when a value is selected and the prompt is no"\r
+ + " longer visible.";\r
+ }\r
+\r
+ @Override\r
+ public APIResource[] getRelatedAPI() {\r
+ return new APIResource[] { new APIResource(ComboBox.class) };\r
+ }\r
+\r
+ @Override\r
+ public Class[] getRelatedFeatures() {\r
+ return new Class[] { ComboBoxStartsWith.class, ComboBoxContains.class,\r
+ ComboBoxNewItems.class, TextFieldInputPrompt.class };\r
+ }\r
+\r
+ @Override\r
+ public NamedExternalResource[] getRelatedResources() {\r
+ return new NamedExternalResource[] { new NamedExternalResource(\r
+ "UI Patterns, Input Prompt",\r
+ "http://ui-patterns.com/pattern/InputPrompt") };\r
+ }\r
+\r
+}\r
--- /dev/null
+package com.itmill.toolkit.demo.sampler.features.selects;\r
+\r
+import com.itmill.toolkit.data.Property;\r
+import com.itmill.toolkit.data.Property.ValueChangeEvent;\r
+import com.itmill.toolkit.ui.ComboBox;\r
+import com.itmill.toolkit.ui.VerticalLayout;\r
+\r
+public class ComboBoxInputPromptExample extends VerticalLayout implements\r
+ Property.ValueChangeListener {\r
+\r
+ private static final String[] cities = new String[] { "Berlin", "Brussels",\r
+ "Helsinki", "Madrid", "Oslo", "Paris", "Stockholm" };\r
+\r
+ public ComboBoxInputPromptExample() {\r
+ setMargin(true); // for looks: more 'air'\r
+\r
+ // Create & set input prompt\r
+ ComboBox l = new ComboBox();\r
+ l.setInputPrompt("Please select a city");\r
+\r
+ // configure & load content\r
+ l.setImmediate(true);\r
+ l.addListener(this);\r
+ for (int i = 0; i < cities.length; i++) {\r
+ l.addItem(cities[i]);\r
+ }\r
+\r
+ // add to the layout\r
+ addComponent(l);\r
+ }\r
+\r
+ /*\r
+ * Shows a notification when a selection is made.\r
+ */\r
+ public void valueChange(ValueChangeEvent event) {\r
+ getWindow().showNotification("Selected city: " + event.getProperty());\r
+\r
+ }\r
+}\r
--- /dev/null
+package com.itmill.toolkit.demo.sampler.features.text;\r
+\r
+import com.itmill.toolkit.demo.sampler.APIResource;\r
+import com.itmill.toolkit.demo.sampler.Feature;\r
+import com.itmill.toolkit.demo.sampler.FeatureSet;\r
+import com.itmill.toolkit.demo.sampler.NamedExternalResource;\r
+import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxInputPrompt;\r
+import com.itmill.toolkit.demo.sampler.features.selects.ComboBoxNewItems;\r
+import com.itmill.toolkit.ui.TextField;\r
+\r
+public class TextFieldInputPrompt extends Feature {\r
+ @Override\r
+ public String getName() {\r
+ return "Text field with input prompt";\r
+ }\r
+\r
+ @Override\r
+ public String getDescription() {\r
+ return " The TextField can have an <i>input prompt</i> - a textual hint that is shown within"\r
+ + " the field when the field is otherwise empty.<br/>"\r
+ + " You can use an input prompt instead of a caption to save"\r
+ + " space, but only do so if the function of the TextField is"\r
+ + " still clear when a value has been entered and the prompt is no"\r
+ + " longer visible.";\r
+ }\r
+\r
+ @Override\r
+ public APIResource[] getRelatedAPI() {\r
+ return new APIResource[] { new APIResource(TextField.class) };\r
+ }\r
+\r
+ @Override\r
+ public Class[] getRelatedFeatures() {\r
+ // TODO update CB -ref to 'suggest' pattern, when available\r
+ return new Class[] { TextFieldSingle.class, TextFieldSecret.class,\r
+ ComboBoxInputPrompt.class, ComboBoxNewItems.class,\r
+ FeatureSet.Texts.class };\r
+ }\r
+\r
+ @Override\r
+ public NamedExternalResource[] getRelatedResources() {\r
+ return new NamedExternalResource[] { new NamedExternalResource(\r
+ "UI Patterns, Input Prompt",\r
+ "http://ui-patterns.com/pattern/InputPrompt") };\r
+ }\r
+\r
+}\r
--- /dev/null
+package com.itmill.toolkit.demo.sampler.features.text;\r
+\r
+import com.itmill.toolkit.data.Property;\r
+import com.itmill.toolkit.data.Property.ValueChangeEvent;\r
+import com.itmill.toolkit.ui.TextField;\r
+import com.itmill.toolkit.ui.VerticalLayout;\r
+\r
+public class TextFieldInputPromptExample extends VerticalLayout implements\r
+ Property.ValueChangeListener {\r
+\r
+ public TextFieldInputPromptExample() {\r
+ // add som 'air' to the layout\r
+ setSpacing(true);\r
+ setMargin(true);\r
+\r
+ // Username field + input prompt\r
+ TextField username = new TextField();\r
+ username.setInputPrompt("Username");\r
+ // configure & add to layout\r
+ username.setImmediate(true);\r
+ username.addListener(this);\r
+ addComponent(username);\r
+\r
+ // Password field + input prompt\r
+ TextField password = new TextField();\r
+ password.setInputPrompt("Password");\r
+ // configure & add to layout\r
+ password.setSecret(true);\r
+ password.setImmediate(true);\r
+ password.addListener(this);\r
+ addComponent(password);\r
+\r
+ // Comment field + input prompt\r
+ TextField comment = new TextField();\r
+ comment.setInputPrompt("Comment");\r
+ // configure & add to layout\r
+ comment.setRows(3);\r
+ comment.setImmediate(true);\r
+ comment.addListener(this);\r
+ addComponent(comment);\r
+\r
+ }\r
+\r
+ public void valueChange(ValueChangeEvent event) {\r
+ getWindow().showNotification("Received " + event.getProperty());\r
+\r
+ }\r
+\r
+}\r
}
if (allowNewItem) {
- if (!enteredItemValue.equals(emptyText)
- && !enteredItemValue.equals(lastNewItemString)) {
+ if (!prompting && !enteredItemValue.equals(lastNewItemString)) {
/*
* Store last sent new item string to avoid double sends
*/
} else {
if (currentSuggestion != null) {
String text = currentSuggestion.getReplacementString();
- tb.setText((text.equals("") ? emptyText : text));
- // TODO add/remove class CLASSNAME_EMPTY
+ /*- TODO?
+ if (text.equals("")) {
+ tb.setText(inputPrompt);
+ prompting = true;
+ addStyleDependentName(CLASSNAME_PROMPT);
+ } else {
+ tb.setText(text);
+ prompting = false;
+ removeStyleDependentName(CLASSNAME_PROMPT);
+ }
+ -*/
selectedOptionKey = currentSuggestion.key;
- } else {
- tb.setText(emptyText);
- // TODO add class CLASSNAME_EMPTY
- selectedOptionKey = null;
}
}
suggestionPopup.hide();
private boolean enabled;
// shown in unfocused empty field, disappears on focus (e.g "Search here")
- private String emptyText = "";
+ private static final String CLASSNAME_PROMPT = "prompt";
+ private static final String ATTR_INPUTPROMPT = "prompt";
+ private String inputPrompt = "";
+ private boolean prompting = false;
+
// Set true when popupopened has been clicked. Cleared on each UIDL-update.
// This handles the special case where are not filtering yet and the
// selected value has changed on the server-side. See #2119
private int textboxPadding = -1;
private int componentPadding = -1;
private int suggestionPopupMinWidth = 0;
- // private static final String CLASSNAME_EMPTY = "empty";
- private static final String ATTR_EMPTYTEXT = "emptytext";
/*
* Stores the last new item string to avoid double submissions. Cleared on
* uidl updates
currentPage = uidl.getIntVariable("page");
- if (uidl.hasAttribute(ATTR_EMPTYTEXT)) {
- // "emptytext" changed from server
- emptyText = uidl.getStringAttribute(ATTR_EMPTYTEXT);
+ if (uidl.hasAttribute(ATTR_INPUTPROMPT)) {
+ // input prompt changed from server
+ inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
+ } else {
+ inputPrompt = "";
}
suggestionPopup.setPagingEnabled(true);
final UIDL options = uidl.getChildUIDL(0);
totalMatches = uidl.getIntAttribute("totalMatches");
- String captions = emptyText;
+ String captions = inputPrompt;
for (final Iterator i = options.getChildIterator(); i.hasNext();) {
final UIDL optionUidl = (UIDL) i.next();
if ((!filtering || popupOpenerClicked) && uidl.hasVariable("selected")
&& uidl.getStringArrayVariable("selected").length == 0) {
// select nulled
- tb.setText(emptyText);
+ if (!filtering || !popupOpenerClicked) {
+ tb.setText(inputPrompt);
+ prompting = true;
+ addStyleDependentName(CLASSNAME_PROMPT);
+ }
selectedOptionKey = null;
- // TODO add class CLASSNAME_EMPTY
}
if (filtering
// normal selection
newKey = String.valueOf(suggestion.getOptionKey());
}
+
String text = suggestion.getReplacementString();
- tb.setText(text.equals("") ? emptyText : text);
- // TODO add/remove class CLASSNAME_EMPTY
+ if ("".equals(newKey)) {
+ tb.setText(inputPrompt);
+ prompting = true;
+ addStyleDependentName(CLASSNAME_PROMPT);
+ } else {
+ tb.setText(text);
+ prompting = false;
+ removeStyleDependentName(CLASSNAME_PROMPT);
+ }
setSelectedItemIcon(suggestion.getIconUri());
if (!newKey.equals(selectedOptionKey)) {
selectedOptionKey = newKey;
case KeyboardListener.KEY_ESCAPE:
if (currentSuggestion != null) {
String text = currentSuggestion.getReplacementString();
- tb.setText((text.equals("") ? emptyText : text));
- // TODO add/remove class CLASSNAME_EMPTY
+ tb.setText(text);
+ prompting = false;
+ removeStyleDependentName(CLASSNAME_PROMPT);
selectedOptionKey = currentSuggestion.key;
} else {
- tb.setText(emptyText);
- // TODO add class CLASSNAME_EMPTY
+ tb.setText(inputPrompt);
+ prompting = true;
+ addStyleDependentName(CLASSNAME_PROMPT);
selectedOptionKey = null;
}
lastFilter = "";
public void onClick(Widget sender) {
if (enabled) {
// ask suggestionPopup if it was just closed, we are using GWT
- // Popup's
- // auto close feature
+ // Popup's auto close feature
if (!suggestionPopup.isJustClosed()) {
filterOptions(-1, "");
popupOpenerClicked = true;
lastFilter = "";
+ } else if (selectedOptionKey == null) {
+ tb.setText(inputPrompt);
+ prompting = true;
}
DOM.eventPreventDefault(DOM.eventGetCurrentEvent());
tb.setFocus(true);
private native int minWidth(String captions)
/*-{
if(!captions || captions.length <= 0)
- return 0;
+ return 0;
captions = captions.split("|");
var d = $wnd.document.createElement("div");
var html = "";
for(var i=0; i < captions.length; i++) {
- html += "<div>" + captions[i] + "</div>";
- // TODO apply same CSS classname as in suggestionmenu
+ html += "<div>" + captions[i] + "</div>";
+ // TODO apply same CSS classname as in suggestionmenu
}
d.style.position = "absolute";
d.style.top = "0";
}-*/;
public void onFocus(Widget sender) {
- if (emptyText.equals(tb.getText())) {
+ if (prompting) {
tb.setText("");
- // TODO remove class CLASSNAME_EMPTY
+ removeStyleDependentName(CLASSNAME_PROMPT);
}
addStyleDependentName("focus");
}
// typing so fast the popup was never opened, or it's just closed
suggestionPopup.menu.doSelectedItemAction();
}
- if ("".equals(tb.getText())) {
- tb.setText(emptyText);
- // TODO add CLASSNAME_EMPTY
+ if (selectedOptionKey == null) {
+ tb.setText(inputPrompt);
+ prompting = true;
+ addStyleDependentName(CLASSNAME_PROMPT);
}
removeStyleDependentName("focus");
}
public void focus() {
+ if (prompting) {
+ tb.setText("");
+ prompting = false;
+ removeStyleDependentName(CLASSNAME_PROMPT);
+ }
tb.setFocus(true);
}
private int extraVerticalPixels = -1;
private int maxLength = -1;
+ private static final String CLASSNAME_PROMPT = "prompt";
+ private static final String ATTR_INPUTPROMPT = "prompt";
+ private String inputPrompt = null;
+ private boolean prompting = false;
+
public ITextField() {
this(DOM.createInputText());
}
setReadOnly(false);
}
+ inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
+
setMaxLength(uidl.hasAttribute("maxLength") ? uidl
.getIntAttribute("maxLength") : -1);
setColumns(new Integer(uidl.getStringAttribute("cols")).intValue());
}
- setText(uidl.getStringVariable("text"));
+ String text = uidl.getStringVariable("text");
+ prompting = inputPrompt != null && (text == null || text.equals(""));
+ if (prompting) {
+ setText(inputPrompt);
+ addStyleDependentName(CLASSNAME_PROMPT);
+ } else {
+ setText(text);
+ removeStyleDependentName(CLASSNAME_PROMPT);
+ }
valueBeforeEdit = uidl.getStringVariable("text");
}
if (newMaxLength > 0) {
maxLength = newMaxLength;
if (getElement().getTagName().toLowerCase().equals("textarea")) {
- // NOP no maxlenght property for textarea
+ // NOP no maxlength property for textarea
} else {
getElement().setPropertyInt("maxLength", maxLength);
}
} else if (maxLength != -1) {
if (getElement().getTagName().toLowerCase().equals("textarea")) {
- // NOP no maxlenght property for textarea
+ // NOP no maxlength property for textarea
} else {
getElement().setAttribute("maxlength", "");
}
public void onChange(Widget sender) {
if (client != null && id != null) {
String newText = getText();
- if (newText != null && !newText.equals(valueBeforeEdit)) {
+ if (!prompting && newText != null
+ && !newText.equals(valueBeforeEdit)) {
client.updateVariable(id, "text", getText(), immediate);
valueBeforeEdit = newText;
}
public void onFocus(Widget sender) {
addStyleDependentName(CLASSNAME_FOCUS);
+ if (prompting) {
+ setText("");
+ removeStyleDependentName(CLASSNAME_PROMPT);
+ }
focusedTextField = this;
}
public void onLostFocus(Widget sender) {
removeStyleDependentName(CLASSNAME_FOCUS);
focusedTextField = null;
+ String text = getText();
+ prompting = inputPrompt != null && (text == null || "".equals(text));
+ if (prompting) {
+ setText(inputPrompt);
+ addStyleDependentName(CLASSNAME_PROMPT);
+ }
onChange(sender);
}
import java.util.Collection;\r
\r
import com.itmill.toolkit.data.Container;\r
+import com.itmill.toolkit.terminal.PaintException;\r
+import com.itmill.toolkit.terminal.PaintTarget;\r
\r
/**\r
* A filtering dropdown single-select. Suitable for newItemsAllowed, but it's\r
*/\r
public class ComboBox extends Select {\r
\r
- private String emptyText = null;\r
+ private String inputPrompt = null;\r
\r
public ComboBox() {\r
setMultiSelect(false);\r
super.setMultiSelect(multiSelect);\r
}\r
\r
- /*- TODO enable and test this - client impl exists\r
- public String getEmptyText() {\r
- return emptyText;\r
+ /**\r
+ * Gets the current input prompt.\r
+ * \r
+ * @see #setInputPrompt(String)\r
+ * @return the current input prompt, or null if not enabled\r
+ */\r
+ public String getInputPrompt() {\r
+ return inputPrompt;\r
}\r
\r
- public void setEmptyText(String emptyText) {\r
- this.emptyText = emptyText;\r
+ /**\r
+ * Sets the input prompt - a textual prompt that is displayed when the\r
+ * select would otherwise be empty, to prompt the user for input.\r
+ * \r
+ * @param inputPrompt\r
+ * the desired input prompt, or null to disable\r
+ */\r
+ public void setInputPrompt(String inputPrompt) {\r
+ this.inputPrompt = inputPrompt;\r
}\r
\r
public void paintContent(PaintTarget target) throws PaintException {\r
- if (emptyText != null) {\r
- target.addAttribute("emptytext", emptyText);\r
+ if (inputPrompt != null) {\r
+ target.addAttribute("prompt", inputPrompt);\r
}\r
super.paintContent(target);\r
}\r
- -*/\r
\r
}\r
import com.itmill.toolkit.terminal.PaintTarget;
/**
- * A simple RichTextEditor to edit HTML format text.
+ * A simple RichTextArea to edit HTML format text.
*
* Note, that using {@link TextField#setMaxLength(int)} method in
* {@link RichTextArea} may produce unexpected results as formatting is counted
super.paintContent(target);
}
+ /**
+ * RichTextArea does not support input prompt.
+ */
+ @Override
+ public void setInputPrompt(String inputPrompt) {
+ throw new UnsupportedOperationException(
+ "RichTextArea does not support inputPrompt");
+ }
+
}
*/
private boolean nullSettingAllowed = false;
+ private String inputPrompt = null;
+
/**
* Maximum character count in text field.
*/
target.addAttribute("maxLength", getMaxLength());
}
+ if (inputPrompt != null) {
+ target.addAttribute("prompt", inputPrompt);
+ }
+
// Adds the number of column and rows
final int c = getColumns();
final int r = getRows();
this.nullSettingAllowed = nullSettingAllowed;
}
+ /**
+ * Gets the current input prompt.
+ *
+ * @see #setInputPrompt(String)
+ * @return the current input prompt, or null if not enabled
+ */
+ public String getInputPrompt() {
+ return inputPrompt;
+ }
+
+ /**
+ * Sets the input prompt - a textual prompt that is displayed when the field
+ * would otherwise be empty, to prompt the user for input.
+ *
+ * @param inputPrompt
+ */
+ public void setInputPrompt(String inputPrompt) {
+ this.inputPrompt = inputPrompt;
+ }
+
/**
* Gets the value formatter of TextField.
*