This commit is contained in:
Peter Saint-Andre 2013-11-11 07:46:00 -08:00
parent 848c901c3d
commit 26ecf4bbc1
1 changed files with 271 additions and 6 deletions

View File

@ -8,9 +8,9 @@
<header>
<title>Data Forms - Dynamic Forms</title>
<abstract>
This specification provides extensions to the data forms model defined in previous XEPs that permits enhanced end-user interaction and
a better user experience. It permits forms to react on user input by permitting the addition, updating or removal of fields in the form,
server-side validation of fields as well as define new states making it possible to display disabled controls,
This specification provides extensions to the data forms model defined in previous XEPs that permit enhanced end-user interaction and
a better user experience. These extensions permit forms to react on user input by permitting the addition, updating or removal of fields in the form
and server-side validation of fields. The extension also defines new states making it possible to display disabled controls,
controls with undefined values or error messages, while still being backwards compatible with the existing data form model with available
extensions.
</abstract>
@ -42,7 +42,17 @@
<jid>peter.waher@jabber.org</jid>
<uri>http://www.linkedin.com/in/peterwaher</uri>
</author>
<revision>
<revision>
<version>0.0.2</version>
<date>2013-10-29</date>
<initials>pw</initials>
<remark>
<p>Added comparison to XEP-0050, Ad-hoc commands.</p>
<p>Added support for server push of asynchronous form changes.</p>
<p>Added an implementation note regarding client-side values.</p>
</remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2013-07-23</date>
<initials>pw</initials>
@ -119,6 +129,12 @@
editing the form.
</p>
</li>
<li>
<p>
Permits spontaneous updates of the form, pushed from the form server to the client showing the form. This might be necessary in
cases where the process of aquiring current values may take some time, but the client is required to show a form right away.
</p>
</li>
</ul>
<p>
<strong>Note:</strong> This extension is only dependent upon the <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link> XEP. It works in
@ -126,7 +142,104 @@
in this document may still reference extensions made in other documents, but these are considered to be examples only, used to illustrate
a specific point or example.
</p>
</section1>
<section2 topic='Comparison to Ad-hoc commands'>
<p>
&xep0050; defines a mechanism to enhance data forms creating dialog wizards with actions that guide the user through pages, where each page
can depend on the input from previous pages. The following list consists of a comparison of the differences between Ad-hoc commands and
Dynamic Forms, and why this extension is not based on the concepts defined in XEP-0050:
</p>
<ul>
<li>
<p>
The main point of this extension is to make the current form dynamic. Pages in a wizard, as defined in ad-hoc commands, are still static
requiring page navigation for the dialog to be updated.
</p>
</li>
<li>
<p>
There might be a desire to make individual pages inside a wizard dynamic by themselves. In this case, this extension might be used to
extend Ad-hoc commands with dynamic pages inside wizards.
</p>
</li>
<li>
<p>
Wizards order their pages linearly, in a one-dimensional array of pages. Navigation is only performed using prev and next actions, and completed with the execute or
complete actions. This might work sufficiently well where page output only is based on input from the previous page. But as soon as the input depends on more pages,
navigation becomes unnecessarily cumbersome. For example a dialog with country, region, city, area, street, building, apartment. To change the country parameter when you
are on the apartment page, requires you to back through many pages, while in the dynamic form you just change the parameter directly, since all are visible
in the same form.
</p>
<p>
The problem gets worse if this is a normal behavior for a form. Say a dialog with a post carrier field, followed by country, city, office, etc.
When the user comes to office and notices that the selected carrier has no office close to you, you change carrier, but don't want to change country and city, if
possible.
</p>
</li>
<li>
<p>
The pages in a wizard do not allow for spontaneous or immediate feedback to the user. Such immediate feedback is of great importance in user-friendly
forms, where complex input is required. Consider the following simple example:
</p>
<p>
Imagine a dialog used for configuring a TCP port scanner to search for specific devices in a network. It might take five parameters: IP range, port range, number of threads,
connection timeout (ms) and number of tries before failing. However, the operator wants to know how much time the operation will take (which is #IP-addresses *
#port numbers * Connection Timeout * Nr Tries / #Threads). To see this in a separate page and then have to go back to the different pages, forwarding to the
time estimate calculation page, etc., is a very cumbersome process. Presenting all this information on a single page using Dynamic Forms is creates a much
better and richer user experience. Changing the value of any of the five parameters will directly update a text parameter presenting the total expected time of the
operation.
</p>
</li>
<li>
<p>
Wizards as defined in Ad-hoc commands are hard-wired to commands as such. Navigation actions are defined outside of the scope of the form itself. This extensions
defines Dynamic Forms as an extension of the Data Form concept. All navigation, post-back fields, etc., are defined within the actual form itself. This makes
it re-usable everywhere data forms are used, including pages inside an Ad-Hoc command wizard.
</p>
</li>
<li>
<p>
Ad-hoc command wizards include the feature to return notes including information, warnings or error information to the user. This information however, is associated
with the current page in the wizard itself. Dynamic Forms contains a means to attach error information directly to individual fields, making feedback more precise.
Together with the server post-back feature immediate server-side validation during user input is possible.
</p>
</li>
<li>
<p>
Dynamic Forms contains a feature that ad-hoc command wizards do not: Read-only fields. These differs from other text fields in that they are rendered as normal
controls, except input is read-only. Together with the server post-back feature this allows the server to enable and disable parameters depending on user
input on the same page. An example can be a checkbox that enabled another field if checked, as a security measure.
</p>
</li>
<li>
<p>
Dynamic Forms defines the concept of an undefined field value. These fields are presented with the available value (if any), but greyed out, signaling to the user that
the value is not well defined for some reason. Perhaps it is only one of many values held my multiple objects in the case when editing multiple objects at once.
Undefined values are not sent back to the server when the form is posted back. When the user edits such a field, the undefined flag is cleared and the field is
presented as a normal control. The main purpose of this flag is to allow for editing multiple objects at once or for editing control forms where current states are
not known at the moment if creating the form.
</p>
</li>
<li>
<p>
Dynamic Forms supports asynchronous updates of the form, where the server can push changes to the form not resulting from user input. This is a powerful feature that
allows the server to update a form being edited by the user to reflect changes on the server. Consider the following examples:
</p>
<p>
Consider a control form containing control fields on a remote device. At the time of displaying the form, the current states of some fields might be unknown. So the fields
are marked perhaps with some default values, but with the undefined flag set for the corresponding fields. At the time of creating the form, a parallel request is made
to the device by the form server, requesting information about current states of the device. When these are received by the server, it issues an update of the form to the
client with the newly received and current field values. The request for values might take some time, so using this mechanism provides a form to the user quickly, clearly
indicating what is missing, and then complements the form when data is available.
</p>
<p>
Another example might be a dialog showing contents on the form server in a multi-user environment where updates to the contents is made. An example can be a file system.
If changes to the contents is made by another user, the server has the possibility to update any current forms to reflect changes made. This decreases the possibility
of inconsistencies in the system, and at the same time increases the user-friendliness of the end-user experience of the application.
</p>
</li>
</ul>
</section2>
</section1>
<section1 topic='Glossary' anchor='glossary'>
<p>The following table lists terms and corresponding descriptions or definitions for use throughout this document.</p>
<dl>
@ -356,6 +469,10 @@
flag instead, gives greater flexibility when it comes to presentation, as well as permitting the form server
to enable and disable controls during the lifetime of the form.
</p>
<p>
<strong>Note 2:</strong> Make sure to check the implementation note <link url='#clientsidevalues'>Merging Client-Side Values</link> for information
on how to merge updates received from the server with current input made by the client.
</p>
</section2>
<section2 topic='Publishing fields with undefined values'>
<p>
@ -481,7 +598,7 @@
</field>
...
</x>
</formPostBack>
</cancel>
</iq>]]>
</example>
<p>
@ -541,6 +658,75 @@
</iq>]]>
</example>
</section2>
<section2 topic='Asynchronous updates of forms (server push)'>
<p>
The server may send asynchronous updates to open forms on the client. This can be done if the server detects changes that it wants to inform
the client about. Changes are made by sending a <strong>message</strong> stanza including a <strong>formUpdated</strong> element which in turn
contains the new updated form.
</p>
<p>
Examples can include a control form showing control parameters. While the server is trying to retrieve the current values
it presents the control form with undefined values, and later when values are received by the server, it sends an update to the client with
actual values.
</p>
<p>
Another example can include a dialog containing information on items on the server in a multi-user environment (for instance a file system).
Changes made by users can be displayed in open dialogs to other users as they change.
</p>
<p>
The client may have more than one form open at any given time. It might also be so that the form has been closed prior to receiving or handling the update message,
and is therefore no longer visible. To be able to identify to which form the update corresponds, the <strong>formUpdated</strong>
element is required to include a <strong>sessionVariable</strong> attribute in which it identifies a <strong>unique</strong> identifying
field in the form. When the client receives the update, it goes through all forms it has open. If a form has a field variable with a corresponding
name, and the field variable has a value equal to the value in the updated form, the form should be updated by the contents of the message. If no form is found,
the update is simply ignored. If multiple forms are found, all should be updated.
</p>
<example caption='Asynchronous update of form (server push)'>
<![CDATA[
<x xmlns="jabber:x:data" type="form"
xmlns:xdd="http://jabber.org/protocol/xdata-dynamic"
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
<title>Control parameters</title>
<field var='xdd session' type='hidden'>
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
</field>
<field var="AnalogOutput" type="text-single" label="Analog Output:">
<desc>Enter a new value for the analog output.</desc>
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:int">
<xdv:range min="0" max="65535"/>
</xdv:validate>
<value>0</value>
<xdd:notSame/>
</field>
</x>
...
<message from='server@clayster.com'
to='client@clayster.com/client'>
<formUpdated xmlns='http://jabber.org/protocol/xdata-dynamic' sessionVariable='xdd session'>
<x xmlns="jabber:x:data" type="form"
xmlns:xdd="http://jabber.org/protocol/xdata-dynamic"
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
<title>Control parameters</title>
<field var='xdd session' type='hidden'>
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
</field>
<field var="AnalogOutput" type="text-single" label="Analog Output:">
<desc>Enter a new value for the analog output.</desc>
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:int">
<xdv:range min="0" max="65535"/>
</xdv:validate>
<value>49152</value>
</field>
</x>
</formUpdated>
</message>]]>
</example>
<p>
<strong>Note:</strong> Make sure to check the implementation note <link url='#clientsidevalues'>Merging Client-Side Values</link> for information
on how to merge updates received from the server with current input made by the client.
</p>
</section2>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If an entity supports the protocol specified herein, regardless if the entity represents a form server or a form client; it MUST advertise
@ -602,6 +788,73 @@
For normal operations, a dynamic form session timeout of 15 minutes is sufficient.
</p>
</section2>
<section2 topic='Merging Client-Side Values' anchor='clientsidevalues'>
<p>
When receiving asynchronous form updates from the server, or when performing a server post-back of a form, it is important
to know how to merge responses from the server with the current form being displayed to the user. As the operation is
asynchronous, and since user input is quick, the user might have input things not known to the server and therefore not
available in form updates. Also, fields not marked for post-back might not have been reported at all to the server, and
therefore, the client is the only one that knows what the user has entered into these fields.
</p>
<p>
So, when receiving form updates, either asynchronously, or as part of a server post-back response, the client needs to merge
the updated form, with the current form. The following rules must be applied. Here, the <strong>updated form</strong> represents the
form in the recent message from the server, the <strong>current form</strong> represents the form currently being edited by the user
and the <strong>resulting form</strong> represents the result of the merger of the updated form and the current form.
</p>
<ul>
<li>
<p>
New fields in the updated form not available in the <strong>current form</strong>, are added as-is to the <strong>resulting form</strong>.
</p>
</li>
<li>
<p>
Fields not available in the <strong>updated form</strong> but available in the <strong>current form</strong>, must be removed from the
<strong>resulting form</strong> regardless if user input is available. Any such user input is lost.
</p>
</li>
<li>
<p>
The order of fields in the resulting form must be the same as the order of fields in the <strong>updated form</strong>.
</p>
</li>
<li>
<p>
Fields available in both the <strong>updated form</strong> and the <strong>current form</strong> are handled depending on if the user has entered
values in the corresponding field in the <strong>current form</strong> or not:
</p>
<ul>
<li>
If the user has <strong>not</strong> edited the value in the corresponding field, the value from the <strong>updated form</strong> is used.
</li>
<li>
If the user has edited the value the corresponding field, the value from the <strong>current form</strong> is used.
</li>
<li>
If the user has edited the value of the corresponding field in the <strong>current form</strong>, but the value is the same as the value
available in the <strong>updated form</strong>, the flag stating that user input has occurred in the field can be cleared.
</li>
</ul>
<br/>
</li>
<li>
<p>
If a field in the <strong>updated form</strong> is flagged as <strong>undefined</strong>, but the <strong>current form</strong> has an edited value,
the form in the <strong>resulting form</strong> must <strong>not</strong> be marked as <strong>undefined</strong>.
</p>
</li>
<li>
<p>
All other properties for fields must be taken from the <strong>updated form</strong> and copied to the <strong>resulting form</strong>.
</p>
</li>
</ul>
<p>
How the above merger is made is implementation specific. One simple implementation can simply be taking the updated form, adding any client-side values to it
(i.e. values edited in the current form) perhaps removing any undefined value flags, and then use the result as a model for the resulting form.
</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>
@ -679,6 +932,15 @@
</xs:complexType>
</xs:element>
<xs:element name='formUpdated'>
<xs:complexType>
<xs:sequence>
<xs:element ref='xd:x' minOccurs='1' maxOccurs='1'/>
</xs:sequence>
<xs:attribute name='sessionVariable' type='xs:string' use='required'/>
</xs:complexType>
</xs:element>
<xs:simpleType name='PostBackResultCode'>
<xs:restriction base='xs:string'>
<xs:enumeration value='OK'/>
@ -704,4 +966,7 @@
</xs:schema>]]>
</code>
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Thanks to Karin Forsell for all valuable feedback.</p>
</section1>
</xep>