- A DateWidget composed of 3 html SELECT elements (month, day and year)
- A custom combobox composed of a textbox, a button (placed to the right of the textbox) and a popup (or more accurately a drop-down) div that contains a pick list and appears when the button is clicked or a letter is typed.
- A DatePicker (same as custom combobox mentioned above, except the drop down is a calendar instead of a pick list)
Below is a problem with this kind of widget that i have not been able to easily solve:
Problem DefinitionIt is often desirable to have a single blur event that applies to the composite as a whole. Using the blur event for the internal html elements may be the wrong granularity for validation or change notifications. For example, suppose that for the above mentioned combobox, we chose to use the textbox's blur event (because the combobox as a whole has no blur event) for validation. Then imagine this scenario:
- The user types 1 letter into the textbox
- The popup appears
- User clicks on the popup - perhaps to scroll the pick list or (in the case of the DatePicker) to scroll the month
- Boom! The TextBox's change and blur events fire.
- Our app, in response to the blur event, attempts to validate
- Our validation function reads the value in the textbox and, detecting that it is only 1 character long, displays an error message.
Desired Behavior
Test #1:
Does the composite widget have its own blur event as distinct from those of its child widgets? And (more to the point) is there an obvious way to add a blur listener to the composite (again, as distinct from its child elements)?
Test #2:
Assuming we passed test #1, does the composite's blur event fire in a way that is logical for the composite as a whole:
Test 2a (comboBox with down-arrow trigger button):
Test 2a (comboBox with down-arrow trigger button):
- Click into the textbox portion of the combobox
- Type a few letters
- Click the down-arrow-button (to reveal the drop down list). This should not fire the composite's blur event.
- The user types 1 letter into the textbox
- This causes the popup calendar to appear
- The popup contains a "Scroll Next Month" button. Click on that. This should not fire the composite's blur event.
Workarounds
This isn't a deal breaker issue for most applications. We can just hold off on validation until later, when the entire form is submitted. But none-the-less, many customers prefer field-level errors to appear sooner rather than later. This is, after all, one of reasons we have blur and change events.
Other Widget Libraries
I did a quick survey of composite widgets from various web widget libraries, to see if they handled blur events as desired (see "desired behavior" above). Here is what I found:
Possible Solutions
Note that what we are describing here is not the same as bubbling. Event bubbling refers to the fact that if a child element does not handle an event (or more specifically cancel the event) then that event bubbles up to the parent element. But a div containing 3 select elements (as in the date selector described above) would still fire 3 change events in either case:
Case #1: three select#changeListeners
Case #2: one div#changeListener.
This is not to say, that bubbling might not be used in the solution. But bubbling, in and of itself, is not the solution.
Objective
Come up with a solution that:
This isn't a deal breaker issue for most applications. We can just hold off on validation until later, when the entire form is submitted. But none-the-less, many customers prefer field-level errors to appear sooner rather than later. This is, after all, one of reasons we have blur and change events.
Other Widget Libraries
I did a quick survey of composite widgets from various web widget libraries, to see if they handled blur events as desired (see "desired behavior" above). Here is what I found:
Library | Widget | Composite blur/change events | Demo Link |
---|---|---|---|
DOJO | dijit.form.FilteringSelect | Yes | TODO |
jQuery | ui.datepicker | No | TODO |
Spry | SuggestText ?? | No | TODO |
GWT 1.5 | SuggestBox | No | TODO |
GWT 1.6 | SuggestBox | Maybe | TODO |
GWT Incubator | DateBox | No | TODO |
Possible Solutions
- Timer solutions. TODO: elaborate
- Global focus tracker. TODO: elaborate
- Try to figure out what DOJO did (their solution was not easy for me to follow)
Note that what we are describing here is not the same as bubbling. Event bubbling refers to the fact that if a child element does not handle an event (or more specifically cancel the event) then that event bubbles up to the parent element. But a div containing 3 select elements (as in the date selector described above) would still fire 3 change events in either case:
Case #1: three select#changeListeners
Case #2: one div#changeListener.
This is not to say, that bubbling might not be used in the solution. But bubbling, in and of itself, is not the solution.
Objective
Come up with a solution that:
- Provides the desired behavior described above
- Is general enough to componentize (for example, in GWT, a generic parent class called BlurableComposite). Note: GWT has a class called FocusPanel, but I can't figure what it's purpose is and if it is designed to address the problem I am describing here.
- If the solution is not general enough to express as a reusable class, then a solution general enough to express in the form of a design pattern/solution
- Perhaps tie in the solution with GWT's new HasValue/HasValueChangeHandler (in 1.6 trunk)
No comments:
Post a Comment