10.3 XForms-specific Design Hints
The following sections describe various small tips and tricks—too small individually to be
10.3.1 Always Include Keyboard Navigation Hints
Every XForms document should include enough information to provide a well-though-out navigation sequence, encompassing both form controls and other elements, such as
Form controls that will be frequently accessed should also include a keyboard shorcut; the details of which are again provided by the host language. The following code shows one possible way to accomplish this, in a host language that uses the techniques suggested by XForms.
<input ref="passwd" accesskey="P" navindex="3"> <label>Password:</label> </input>
10.3.2 Always Use P3P Datatypes
property during form authoring is easy, and it provides one huge benefit: autofill. Most browsers have
P3P datatypes neatly solve this problem. As a model item property,
<bind nodeset="first_name" p3ptype="user.name.given"/> <bind nodeset="last_name" p3ptype="user.name.family"/> <bind nodeset="screen_name" p3ptype="user.login.id"/> <bind nodeset="password" p3ptype="user.login.password"/> <bind nodeset="year_of_birth" p3ptype="user.bdate.ymd.year"/> <bind nodeset="home_telephone" p3ptype="user.home-info.telecom.telephone"/> <bind nodeset="company_name" p3ptype="business.name"/> <bind nodeset="spouse_name" p3ptype="thirdparty.name.given"/>
For more details and examples, refer to the P3P specification at http://www.w3.org/TR/P3P/.
10.3.3 Don't Use a Form for Navigation
As of this writing, it is still common for web sites to use forms (usually a drop-list) for navigation purposes. You select something from the list, and you're whisked away to another page. This approach is increasingly unnecessary as XHTML 2.0 advances, such as including a special element nl for navigation lists. In SVG or other languages, it might, at times, still be necessary to use forms for navigation, but the most specific tool available is usually the right one to use. If you have no choice but to use XForms for navigation, code along the following lines will do the trick.
<select1 ref="..." appearance="minimal"> <item> <label>Go to destination 1</label> <value>...</value> <load ev:event="xforms-select" resource="http://url-for-destination-1" show="replace"/> </item> <item> <label>Go to destination 2</label> <value>...</value> <load ev:event="xforms-select" resource="http://url-for-destination-2" show="replace"/> </item> </select1>
10.3.4 Concatenating a Currency Symbol or Special Character
" 100". The catch is that if the user gets clever and initially enters " 100", it should still work.
This can be accomplished using the if( ) function:
<bind nodeset="cost" calculate="if( starts-with(€, '?'), ., concat( '?',€ ))"/>
This calculation gets a little confusing with all the dots, which represent the current value. Another way to think of it is as pseudo-code:
if ( current value starts with currency symbol ) return current value else return currency symbol concatenated with current value
Instead of hard-coding a currency symbol, the appended string could easily be taken from elsewhere in the instance data. Accomplishing this is left as an exercise for the reader.
10.3.5 Server-Side Database Lookups
A popular feature in advanced form systems is the ability to perform a lookup based on a remote database. For example, a governmental system might want to call up
In XForms, this is possible through the replace attribute on the element submission . A form submission always results in a response. Normally, the response is a new web page to display in place of the form that was just submitted. It is possible, however, to get an XML response back that is used as new instance data for the form—exactly what is needed for database lookups.
One complication is that the form at the time of initiating the lookup might be only partially completed. Normally, this would cause problems on any data items that are considered required. The workaround is to include a special flag that temporarily relaxes required validations, like this:
<model> <instance id="main">...</instance> <bind nodeset="some_data" required="instance('strict_flag')"/> <submission id="send_data" ... /> <submission id="do_lookup" replace="instance" ... /> <instance id="strict_flag"> <flag>true</flag> </instance> </model>
With code such as this in place, a trigger kicks off the database lookup:
<trigger> <label>Lookup</label> <action ev:event="DOMActivate"> <setvalue ref="instance('strict_flag')">false</setvalue> <send submission="do_lookup"/> </action> </trigger>
The sequence of XForms Actions used here first sets the strict flag to false, then submits the data. By referencing the submission element with an ID of do_lookup , the response from the server (which must be XML-suitable as instance data) is used to continue with the form.
Database validations can be achieved in a similar manner, by returning a validity flag in the XML.
10.3.6 Reliably Submitting the Form with Enter
Popular search engines
Figure 10-1. The unreliable effects of the Enter key
Tip: For most browsers you can just press the Return or Enter key, instead of clicking on the search button.
In XForms, this can be accomplished reliably. Even better, the solution isn't dependent on the Enter key, so it will work on
The answer lies with the DOMActivate event, which occurs for a form control when the Enter key (or some equivalent) is, pressed or activated. XML Events take care of the rest, given code like this:
<input ref="q"> <label>Search</label> <send submission="id_of_submission_element" ev:event="DOMActivate"/> </input>
One consideration for extremely small devices is that even refreshing the display can take long enough that it would be annoying if it
Through XML Events, it is possible to cancel all xforms-refresh events before they reach their target, which will prevent all automatic refreshes from happening. All that is needed is one extra attribute from XML Events, like this:
<model ev:event="DOMActivate" ev:propagate="stop"> ... </model>
With that change, all that is needed is a trigger to refresh manually:
<trigger> <label>Refresh Display</label> <refresh ev:event="DOMActivate"/> </trigger>