Every XForms document should include enough information to provide a well-though-out navigation sequence, encompassing both form controls and other elements, such as hyperlinks, from the host language. The exact details on how to do this will vary depending on the host language, though XForms provides a sample implementation based on an attribute called navindex.
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>
The least understood model item property in XForms is probably p3ptype. The W3C P3P specification defines a comprehensive set of rules about identifying what kinds of data collection take place on a web site, at a very granular level. P3P includes rules to define such datatypes, but of main interest to XForms authors are the built-in types defined as part of the base data schema.
Adding the p3ptype property during form authoring is easy, and it provides one huge benefit: autofill. Most browsers have adapted to allow the values in forms to be recalled and repopulated later, removing the need to have to re-enter information. This works by looking at the name and label of the form control. In XForms, labels can include markup, or even refer to instance data or other files. And instead of simple names, form controls have an XPath expression. Combined, these aspects make it harder for an XForms browser to tell reliably whether two controls from different forms are really collecting the same data.
P3P datatypes neatly solve this problem. As a model item property, p3ptype associates to the actual data, not to the form control, which is a view on the data. Some examples:
<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"/>
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>
Some commonly requested features are possible in XForms, though not obviously so. One such task is concatenating a currency symbol to an entered value. As an example, if the user enters "100", the value that ends up in the data should really be "€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.
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 taxpayer details based on a unique identifier. Privacy issues alone, not to mention sheer size, prevent this from working in the local context. So, what's needed is a way to submit a partially valid form to a server, to get a partial response back.
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.
Popular search engines pride themselves on a minimal interface—typically just a single entry box with a search button. In most cases, the button isn't even necessary. Just hitting enter in the entry box is enough. This useful functionality, however, has never been standardized before. In fact, one search engine detects that you've pushed the button instead of just hitting enter and responds with a tip, as shown in 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 cell phones, voice browsers, and other such systems.
<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 happened automatically. In such situations, it is possible to disable all automatic refreshing, instead using a trigger to explicitly refresh on demand.
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>
<trigger> <label>Refresh Display</label> <refresh ev:event="DOMActivate"/> </trigger>