Details
-
Type: New Feature
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 3.1.0.BETA1, 3.1
-
Component/s: ACE-Components
-
Labels:None
-
Environment:ICEfaces 3, ACE Components
-
Assignee Priority:P1
-
Affects:Documentation (User Guide, Ref. Guide, etc.), Sample App./Tutorial
Description
- ThemeRoller styling support
- ace:ajax support
- promptLabel attribute (displays inside the inputText when the component doesn't have a value and is not focussed)
- Custom styling for invalid state (red border, etc. if entered value fails validation), and required (see
- "autoTab" boolean attribute, when true the component will automatically tab to the next component once the "maxLength" number of characters have been entered. Facilitates high-speed data-entry use-cases.
-
- screenshot-1.png
- 251 kB
-
- screenshot-10.png
- 284 kB
-
- screenshot-11.png
- 223 kB
-
- screenshot-12.png
- 229 kB
-
- screenshot-13.png
- 243 kB
-
- screenshot-14.png
- 242 kB
-
- screenshot-2.png
- 259 kB
-
- screenshot-3.png
- 276 kB
-
- screenshot-4.png
- 294 kB
-
- screenshot-5.png
- 300 kB
-
- screenshot-6.png
- 280 kB
-
- screenshot-7.png
- 283 kB
-
- screenshot-8.png
- 284 kB
-
- screenshot-9.png
- 278 kB
Issue Links
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
[4/26/2012 5:09:52 PM] Mark Collette: A. Use onfocus to clear prompt, use onchange/onblur to check for empty field and put it prompt with sentinel value. On server if contains sentinel value, clear field before setting submittedValue
[4/26/2012 5:11:29 PM] Mark Collette: B. Server renders iframe with flag set, use onfocus to clear prompt, use onchange/onblur to check for empty field and put prompt in and set hidden field flag. On server if hidden field has flag set clear value before field before setting submittedValue
If the field has no "name" it is also not normally submitted,
so it may be possible to conditionally set the name when the
placeholder is cleared (depending on how jsf.js handles null
values, either having no name attribute, an empty name attribute,
or a bogus name attribute may work).
Ted.
Done using Ted's suggestion of using a bogus "name" as a flag. (Simplest solution.) Flag checked on sever side. (To avoid complications from cross-browser event ordering and handling and interference in bridge submit functions.) Prompt label could be entered as valid value. Markup is like this:
<ace:textEntry id="myFirstName" value="#
{textEntryBean.firstName}" promptLabel="first name">
<ace:ajax render="firstNameOutput" listener="#
"/>
</ace:textEntry>
See video at http://screencast.com/t/1TLUaHDDrjgV.
Revision: 28899
Added : /icefaces3/trunk/icefaces/ace/component/resources/icefaces.ace/textentry
Added : /icefaces3/trunk/icefaces/ace/component/resources/icefaces.ace/textentry/textentry.js
Modified : /icefaces3/trunk/icefaces/ace/component/resources/icefaces.ace/themes/rime/theme.css
Modified : /icefaces3/trunk/icefaces/ace/component/resources/icefaces.ace/themes/sam/theme.css
Added : /icefaces3/trunk/icefaces/ace/component/src/org/icefaces/ace/component/textentry
Added : /icefaces3/trunk/icefaces/ace/component/src/org/icefaces/ace/component/textentry/TextEntry.java
Added : /icefaces3/trunk/icefaces/ace/component/src/org/icefaces/ace/component/textentry/TextEntryMeta.java
Added : /icefaces3/trunk/icefaces/ace/component/src/org/icefaces/ace/component/textentry/TextEntryRenderer.java
Initial work on highlighting error field done. Works like this: http://screencast.com/t/6oK25ZYC.
There is already a ui-state-error style class in theme.css:
- use it for both invalid and required states?
- use it for invalid state and invent class for required state?
- disregard it and invent class(es) for invalid and required states?
- what about the conversion error state?
All these states use the same valid flag. So by the time we get to re-rendering, we can't tell them apart anymore. We have to repeat the logic (not trivial) in the conversion/validation phase.
And what about the initial rendering? Assume all valid? If not we have the same complications as above.
Render extra asterisk for required state?
[5/1/2012 4:43:09 PM] Ken Fyten: requiredIndicator="*"
[5/1/2012 4:43:45 PM] Ken Fyten: requiredIndPosition="left/right"
http://justaddwater.dk/2006/03/29/how-to-indicate-required-or-optional-form-fields/
http://www.usabilitycounts.com/2009/11/18/form-design-and-the-fallacy-of-the-required-field/
[5/1/2012 5:37:20 PM] Ken Fyten: We should make sure that we have a custom style class for required fields as well, in case they just want to color the field or something instead of using a requiredIndicator.
[5/1/2012 5:38:02 PM] Ken Fyten: Another interesting thought is that they might want to indicate if a field is optional (not required) instead of required. We could use the same approach as we've outlined for the requiredIndicator, but add an optionalIndicator as well.
[5/1/2012 5:38:11 PM] Ken Fyten: They could use one, or the other, or both.
According to what I've read on the web, the label attribute is used only in formatting <h:message> or <h:messages>. It is not supposed to be rendered anywhere. So no label can be output.
Required and optional state indicators done. See screenshot-1. Markup looks like this:
<ace:textEntry id="myFirstName" value="#
{textEntryBean.firstName}" promptLabel="first name" required="true" requiredIndicator="*">
<ace:ajax render="@this firstNameOutput" listener="#
"/>
<f:validateLength minimum="5" maximum="10"/>
</ace:textEntry>
<ace:textEntry id="myLastName" value="#
{textEntryBean.lastName}" promptLabel="last name" optionalIndicator="[optional]" optionalIndPosition="left">
<ace:ajax render="@this lastNameOutput" listener="#
"/>
</ace:textEntry>
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\resources\icefaces.ace\textentry\textentry.js
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\src\org\icefaces\ace\component\textentry\TextEntryMeta.java
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\src\org\icefaces\ace\component\textentry\TextEntryRenderer.java
Completed: At revision: 28915
autoTab:
[5/1/2012 4:58:35 PM] Ken Fyten: Have you tried using $("input").trigger( 'keypress', [{preventDefault:function(){},keyCode:9}] );.
Doesn't work. Keycode passed successfully to keypress listener, but no character is output. Tested with keycode 65 ("a") as well.
"No you miss understood the concept. This is not how is it supposed to work. trigger will only call the event handler. It will not actually print the key." (http://stackoverflow.com/questions/832059/definitive-way-to-trigger-keypress-events-with-jquery.)
[5/1/2012 5:00:54 PM] Ted Goddard: "The best I can get is a "tab space" to be inserted after my text " (http://stackoverflow.com/questions/3140616/simulate-tab-keypress-event-in-selenium-rc.)
So we are back to using focus() on the next tab field. But how do you figure out what the next tab field is? Not as simple as it seems.
[5/1/2012 4:54:59 PM] Ken Fyten: function moveOnMax(field,nextFieldID){
if(field.value.length >= field.maxLength)
}
[5/1/2012 4:57:16 PM] Ken Fyten: $(this).parents('form:eq(0),body').find('button,input,textarea,select');
[5/1/2012 4:57:16 PM] Ken Fyten: $(this).parents('form:eq(0),body').find(':input').not('[type=hidden]');
[5/1/2012 4:57:16 PM] Ken Fyten:
var fields = $(this).parents('form:eq(0),body').find(':input').not('[type=hidden]');
var index = fields.index( this );
if ( index > -1 && ( index + 1 ) < fields.length )
This just finds the next (DOM order) input field in the current form. But what about:
- multiple forms? (stop at end of form? tab to next form? loop back in current form?)
- disabled fields, readonly fields?
- tabindex in input fields?
- ARIA tabindex (applicable to all elements, not just input fields)? (ARIA rules are quite complicated.)
[5/1/2012 4:59:49 PM] Nils Lundquist: http://stackoverflow.com/questions/7303507/simulating-the-tab-keydown-focusing-next-element-as-determined-by-tabindex
This has a semblance of a more robust solution. But see how a seemingly simple problem could get ridiculously complicated?
Even more gotcha's:
- need to check for existence/validity of maxLength
- in a keypress listener, field.value.length is actually always one character behind, because the character is not inserted until after the listener is done. At least it is so in Firefox.
- need to watch out for special characters like backspace, delete, CTRL-A, etc.
- use keyup event? what if user presses and holds a key?
After further review and consideration, it seems that it would be useful to further expand the "label" functionality of this component to also support rendering the label outside of the component, thus completely removing the need to use a separate h:outputLabel component at all.
- Change "promptLabel" attr. name to "label". This will facilitate its use for setting the component name in the default h:message(s) error messages, as well as defining it for rendered label. If no "label" attribute is defined, we do not render any label.
- Add new "labelPosition" attribute. Supported values are "left/right/top/bottom/center" with "center" being embedded in the component value region and also the default.
- Collapse the two "requiredIndicatorPosition" and "optionalIndicatorPosition" attributes into a single "indicatorPosition" attribute.
- Expand the supported values for the "indicatorPosition" attribute to be "left/right/top/bottom/labelLeft/labelRight/labelTop/labelBottom". "left/right" etc. position the indicator to the matching location around the input component itself. "labelLeft, labelRight, etc." position the indicator around the label.
- Ensure that the label, indicator(s), and input each have their own CSS classes for customization.
See screenshots-1 to -4 for more common layouts.
When labelPosition is "center", input, label and indicator all become one. Therefore, indicatorPosition can't be labelTop or labelBottom; nor can there be separate CSS classes. See screenshot-2.png.
Certain combinations of positions (e.g. indicatorPosition="top" labelPosition="left", indicatorPosition="labelTop" labelPosition="right") would produce strange layout, and they would require the use of CSS float, which may not work consistently across browsers. See screenshot-5. Or should we use table? (Clumsy.) Use JS to do markup on client-side? (Would cause DOM diff. problems?) Don't allow such layouts and use defaults or best guesses? (Many possible combination scenarios.)
labelTop and labelBottom positions eliminated.
All done using just <span> and <br>. See screenshot-6.png to -10.png for all possible layouts. Some of them still look weird.
In screenshot-6.png, the top and bottom indicators are aligned using a hidden label with the same style class as the displayed label. So changing the style of the label like font size or margin, etc should still keep the alignment. (Truly cross-browser solution?) Fancy markup, CSS, or dynamic JS positioning avoided. (They could be major time sinks later when cross-browser issues will inevitably show up from time to time. E.g. the use of "float" in the submenu indicator arrow of the 1.8 menu item.)
autoTab:
Using keyup event instead of keypress event avoids some complications like field length always one behind. Browser will also stop input at maxlength when user presses and holds key to repeat keystrokes (producing multiple keypress events).
However, some special keys like backtab (Shift-Tab) still behaves strangely. (Backtabbing to maxlength field will immediately tab to next field again automatically.) Need to figure out what's happening and filter out those keys for special processing, if possible.
Code for determining the next tabbable field can be copied from whatever links suggested previously and plugged in as a utility function. For testing, right now just use simplest code of looking up the next input field (with no checking for disabled, readonly, hidden, tabindex etc) in current form.
Showcase demo done based on masked entry demo. See screenshot-11.png.
Adding: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\java\org\icefaces\samples\showcase\example\ace\textEntry
Adding: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\java\org\icefaces\samples\showcase\example\ace\textEntry\TextEntryBean.java
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\java\org\icefaces\samples\showcase\view\navigation\AceMenu.java
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\resources\org\icefaces\samples\showcase\view\resources\messages.properties
Adding: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\webapp\resources\examples\ace\textEntry
Adding: C:\svn\ossrepo\icefaces3\trunk\icefaces\samples\showcase\showcase\src\main\webapp\resources\examples\ace\textEntry\textEntry.xhtml
Completed: At revision: 29007
It would be improved if the CSS was adjusted to add necessary white-space / padding between the label and the input field for each orientation, and the same for the req/opt indicators.
Once that is done, try adapting it to work with the maskedEntry component. Remember that it would be ideal if we could abstract as much of it as possible into a utility class, or if necessary, and ancestor class that our input comps inherited from.
Ken
Rearranged layout, added spacing and dynamic changing of indicator and label positions.
Left labels are aligned by using display:inline-block or float:left. But most likely neither is going to work across all browsers, browser modes, browser versions, or all layout scenarios. (Witness the time-consuming problems caused by the floating right indicator arrow in the 1.8 menu component.) See screenshot-13.png.
We also have to think about whether it's better to leave the spacing and alignment CSS out of theme.css. (Unless we use the same labelPosition/indicatorPosition combination throughout the website. Styling spacing for one position combination may affect spacing in another position combination.)
adapting it to work with the maskedEntry: (and autocompleteEntry and dateTimeEntry)
renderer:
First attempt at moving some utility methods to super InputRenderer class. See them working in MaskedEntry: screenshot-14.png. Note that in-field label is not applicable because the input field has all kinds of masks, placeholders, formatting, key listeners, etc. controlled by the component plugin JS.
component:
Should move common attributes to some common super meta class. But how? (Adding directly to HtmlInputTextMeta or adding an intermediate meta class didn't work.) Also, DateTimeEntry doesn't inherit from HtmlInputText, so has to repeat the attributes? (No multiple inheritance.)
Additional attributes copied and pasted to component meta classes for MaskedEntry, AutoCompleteEntry and DateTimeEntry. DateTimeEntry requires extra label property because it doesn't inherit from HtmlInputText.
Label/indicator (except in-field position and related JS handling) and optional/required/invalid states done for MaskedEntry, AutoCompleteEntry and DateTimeEntry, using refactored utility methods.
autoTab implemented with some limitations (see below) using keypress event.
ice.ace.util.findNextTabElement() function created from code at link suggested previously: http://stackoverflow.com/a/7329696.
Can't use keyup event because key combinations like Ctrl-A generate separate key events, but somehow the event.ctrlKey flag is not set for the "A" character event, making it indistinguishable from the non-modified "A" character event.
In keypress event, character isn't inserted until after listener. Therefore the submit (triggered by current element blur, which in turn is triggered by the next element focus) will always have one character missing.
To overcome this, we have to intercept the character and insert it manually before the next element focusing. However, this creates other even more complicated problems. If we assume that the cursor is always at the end, we can just append the character. But what if the cursor is not at the end?
Another related limitation: can't type to replace highlighted text. To solve this we need to resort to messy browser-specific text selection API?
General limitation: likely works in common cases only. Impossible for it to work with all browsers, all keyboards, all input methods, ... That will be the job of the textinput event in DOM 3. (Hopefully.) See David Flanagan, "JavaScript: The Definitive Guide" 6th ed., sections 17.8, 17.9.
Moved findNextTabElement() to core.js to avoid having to load ace-yui.js.
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\resources\icefaces.ace\core\core.js
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\resources\icefaces.ace\textentry\textentry.js
Modified: C:\svn\ossrepo\icefaces3\trunk\icefaces\ace\component\resources\icefaces.ace\util\util.js
Completed: At revision: 29226
promptLabel attribute implemented. Works like placeholder attribute in HTML5. Styling of input field mostly by existing style classes in theme.css (like MaskedEntry), with addition of ui-prompt-label. See video at http://screencast.com/t/0X20AlqNE3.