mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-27 11:42:17 -05:00
3c5f20a4ca
sed -i 's/\s\+$//' xep-*.xml
973 lines
50 KiB
XML
973 lines
50 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [
|
|
<!ENTITY % ents SYSTEM 'xep.ent'>
|
|
%ents;
|
|
]>
|
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
|
|
<xep>
|
|
<header>
|
|
<title>Data Forms - Dynamic Forms</title>
|
|
<abstract>
|
|
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>
|
|
&LEGALNOTICE;
|
|
<number>0336</number>
|
|
<status>Deferred</status>
|
|
<type>Standards Track</type>
|
|
<sig>Standards</sig>
|
|
<approver>Council</approver>
|
|
<dependencies>
|
|
<spec>XMPP Core</spec>
|
|
<spec>XEP-0004</spec>
|
|
</dependencies>
|
|
<supersedes/>
|
|
<supersededby/>
|
|
<shortname>dynamic-forms</shortname>
|
|
&peterwaher;
|
|
<revision>
|
|
<version>0.2</version>
|
|
<date>2015-11-09</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Updated contact information.</p>
|
|
<p>Updated example JIDs to example.org</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.1</version>
|
|
<date>2014-01-08</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Initial published version approved by the XMPP Council.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.4</version>
|
|
<date>2013-12-18</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>The element formPostBack has been renamed to <strong>submit</strong>.</p>
|
|
<p>The element formUpdated has been renamed to <strong>updated</strong>.</p>
|
|
<p>The elements formPostBackResponse and cancelResponse have been removed. Error handling has been updated to conform to use IQ error stanzas and error codes.</p>
|
|
</remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.3</version>
|
|
<date>2013-12-04</date>
|
|
<initials>pw</initials>
|
|
<remark>
|
|
<p>Namespace changed to urn:xmpp:xdata:dynamic.</p>
|
|
</remark>
|
|
</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>
|
|
<remark>
|
|
<p>First draft.</p>
|
|
</remark>
|
|
</revision>
|
|
</header>
|
|
<section1 topic='Introduction' anchor='intro'>
|
|
<p>
|
|
Data forms are used in many XEPs and provide a mechanism whereby a form can be hosted on one end and displayed on another. XMPP data forms are
|
|
defined and enhanced in many different XEPs, as is shown in the following list:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<p>
|
|
&xep0004; defines the basics of data forms: How forms are defined, sent to the recipient, how the recipient submits forms (or cancels them)
|
|
and how results can be returned. It defines the concepts of field, field type and field value.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
&xep0122; enhances the data forms architecture permitting rules for client-side validation of fields in the form.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
&xep0137; defines a new data type that can be used to publish file upload controls.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
&xep0141; enhances the data forms architecture permitting the form to have pages or tabs with sections containing grouped controls.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
&xep0221; defines a means to include content such as images, video or audio in forms.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
&xep0331; permits the publication of color fields, where the end user can be presented with a color picker dialog instead of having to
|
|
enter a color value manually or select one from a limited list of colors.
|
|
</p>
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
This specification enhances the data form model further by providing the following features:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<p>
|
|
Form post-back when fields flagged for post-back are edited. This permits the form to adapt itself based on user input, i.e. creating, changing
|
|
or removing fields in the form, creating dynamic forms. It also provides a mechanism to publish server-side validation of fields during user input.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Allows fields to be disabled. They will be shown as normal controls, but in a disabled state. Combining post-back form
|
|
fields it is possible to enable and disable (or add or remove) fields depending on user input.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Allows fields to have not well-defined values. This can be used for instance, when a value is unknown or when multiple objects
|
|
are edited at the same time in the same form and the objects have different values for the corresponding field.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Permits fields to have errors flagged on them. This can be used to give users intuitive feedback on errors in forms. Together
|
|
with post-back fields, this provides a mechanism whereby server-side validation of fields can be made while the user is still
|
|
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
|
|
parallel with any of the above mentioned data form extensions, but do not require that any of them are supported. The examples provided
|
|
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>
|
|
<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>
|
|
<di>
|
|
<dt>Control</dt>
|
|
<dd>
|
|
The visual control used to display a <strong>field</strong>.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Data Form</dt>
|
|
<dd>
|
|
A form of parameters (a.k.a. fields), as defined in <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link>.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Field</dt>
|
|
<dd>
|
|
A field representing a parameter or control, in a data form, as defined in <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link>.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Form Client</dt>
|
|
<dd>
|
|
For simplicity, we will call the XMPP client that fills in the data form, the <strong>form client</strong>.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Form Server</dt>
|
|
<dd>
|
|
For simplicity, we will call the XMPP client that hosts a data form, the <strong>form server</strong>.
|
|
</dd>
|
|
</di>
|
|
<di>
|
|
<dt>Parameter</dt>
|
|
<dd>
|
|
Used sometimes synonymously with <strong>field</strong>.
|
|
</dd>
|
|
</di>
|
|
</dl>
|
|
</section1>
|
|
<section1 topic='Use Cases' anchor='usecases'>
|
|
<p>
|
|
The following subsections list use cases for the different enhancements defined by this extension. Elements are defined using the namespace
|
|
<strong>urn:xmpp:xdata:dynamic</strong> and namespace prefix <strong>xdd</strong>.
|
|
</p>
|
|
<section2 topic='Publishing post-back fields'>
|
|
<p>
|
|
Post-back fields are fields that require the client to post the form to the server after being edited. This permits the server
|
|
to perform server-side validation on the field, provide immediate user feed-back and change the form according to user input.
|
|
</p>
|
|
<p>
|
|
Post-back fields are declared as normal fields in a form, except they also have the <strong>xdd:postBack</strong> flag present in
|
|
the declaration, as is shown in the following example:
|
|
</p>
|
|
<example caption='Publishing post-back fields'>
|
|
<![CDATA[
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp:xdata:dynamic"
|
|
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
|
|
<title>Current location</title>
|
|
<instructions>Select your current location to continue.</instructions>
|
|
<field var='xdd session' type='hidden'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="Country_ISO_3166_1" type="list-single" label="Country:">
|
|
<desc>Select your country of residence.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:string">
|
|
<xdv:basic/>
|
|
</xdv:validate>
|
|
<value/>
|
|
<xdd:postBack/>
|
|
<option label="Chile">
|
|
<value>CL</value>
|
|
</option>
|
|
<option label="Sweden">
|
|
<value>SE</value>
|
|
</option>
|
|
<option label="United States">
|
|
<value>US</value>
|
|
</option>
|
|
...
|
|
</field>
|
|
</x>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> A system maintaining multiple dynamic forms open at the same time needs to maintain control
|
|
of available open forms. This can be done using a hidden session variable, as is shown in the example above. How this
|
|
is done however, is implementation specific.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Performing a server post-back'>
|
|
<p>
|
|
A server post-back is performed by sending an IQ set stanza with a <strong>submit</strong> child element containing the
|
|
current state of the form. The type of the form must be <strong>submit</strong>. The client should also provide the current
|
|
user language in a <strong>xml:lang</strong> attribute, if available.
|
|
</p>
|
|
<example caption='Performing a server post-back'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='formclient@example.org/client'
|
|
to='formserver@example.org'
|
|
id='1'>
|
|
<submit xmlns='urn:xmpp:xdata:dynamic' xml:lang='en'>
|
|
<x xmlns="jabber:x:data" type="submit">
|
|
<field var='xdd session'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="Country_ISO_3166_1">
|
|
<value>CL</value>
|
|
</field>
|
|
</x>
|
|
</submit>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
It is important to note that this server post-back is part of editing the form, and must not be treated by the server as a final
|
|
submission of the data form.
|
|
</p>
|
|
<p>
|
|
As a response to a successful form post-back, the server returns the new data form, as is shown in the following example:
|
|
</p>
|
|
<example caption='Post-back response'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='formserver@example.org'
|
|
to='formclient@example.org/client'
|
|
id='1'>
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp:xdata:dynamic"
|
|
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
|
|
<title>Current location</title>
|
|
<instructions>Select your current location to continue.</instructions>
|
|
<field var='xdd session' type='hidden'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="Country_ISO_3166_1" type="list-single" label="Country:">
|
|
<desc>Select your country of residence.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:string">
|
|
<xdv:basic/>
|
|
</xdv:validate>
|
|
<value>CL</value>
|
|
<xdd:postBack/>
|
|
<option label="Chile">
|
|
<value>CL</value>
|
|
</option>
|
|
<option label="Sweden">
|
|
<value>SE</value>
|
|
</option>
|
|
<option label="United States">
|
|
<value>US</value>
|
|
</option>
|
|
...
|
|
</field>
|
|
<field var="Region_ISO_3166_2" type="list-single" label="Region:">
|
|
<desc>Select your region of residence.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:string">
|
|
<xdv:basic/>
|
|
</xdv:validate>
|
|
<value/>
|
|
<xdd:postBack/>
|
|
<option label="Antofagasta">
|
|
<value>AN</value>
|
|
</option>
|
|
<option label="Arica y Parinacota">
|
|
<value>AP</value>
|
|
</option>
|
|
<option label="Atacama">
|
|
<value>AT</value>
|
|
</option>
|
|
...
|
|
</field>
|
|
</x>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
In this example, the server adds a new parameter to the form, containing options that depend on the value of the first parameter.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> Server post-back should be made after the user is done editing a post-back field, but before actually navigating to the
|
|
next field. It should not be done while the user is editing the field. For check boxes or list boxes, it is easy for the application
|
|
to decide when the field has been edited, since the application can react to the controls click event. But for text edit boxes, you
|
|
cannot perform a server post-back only just because the text property of the control has changed. You need to wait until the user
|
|
leaves the control or something similar. However, as new fields can be added to the form, the client should wait for the response
|
|
before deciding which control is the next control to go to.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Publishing read-only fields'>
|
|
<p>
|
|
Read-only fields should be laid out on the form just as a similar but editable field would, except editing should be disabled. Together with
|
|
post-back fields, this option allows the form to enable/disable fields depending on user input. Read-only fields are declared as normal fields
|
|
in a form, except they also have the <strong>xdd:readOnly</strong> flag present in the declaration, as is shown in the following example:
|
|
</p>
|
|
<example caption='Publishing read-only fields'>
|
|
<![CDATA[
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp:xdata:dynamic"
|
|
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
|
|
<title>Object properties</title>
|
|
<field var='xdd session' type='hidden'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="ID" type="text-single" label="ID:">
|
|
<desc>ID of object.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:string">
|
|
<xdv:basic/>
|
|
</xdv:validate>
|
|
<value>Object 1</value>
|
|
<xdd:readOnly/>
|
|
</field>
|
|
<field var="RenameID" type="boolean" label="Rename object">
|
|
<desc>To avoid accidental renaming of the objcet, this box must be checked to rename the object.</desc>
|
|
<value>0</value>
|
|
<xdd:postBack/>
|
|
</field>
|
|
...
|
|
</x>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> Using this flag is different from the field type <strong>fixed</strong> defined in
|
|
<link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link>. Fields of type <strong>fixed</strong>
|
|
can also be used to display read-only content. However, this is done as static text, and not as a disabled
|
|
control, specific for the type of content corresponding to the data in question. Using the <strong>readOnly</strong>
|
|
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>
|
|
There are many cases where you want to flag a control as having an <strong>undefined value</strong> or an
|
|
<strong>uncertain</strong> value, instead of simply a missing value. This permits the form client to display the
|
|
control in a specific way (for instance greyed), and omit the field when submitting the form back to the server,
|
|
to avoid errors.
|
|
</p>
|
|
<p>
|
|
This technique can be used for instance, when editing the properties of multiple objects at the same time. Attributes
|
|
that are equal among the objects can be reported as normal fields, while attributes that have different values among
|
|
the objects, can be reported as having a value that is not the same everywhere. The client can then show the
|
|
corresponding control greyed and omitting it in submissions of the form. If the user edits the control however, the
|
|
form client can remove the flag and render the control normally. Submitting the now well-defined field value will
|
|
set the corresponding attribute in all objects to the same new value. Omitting undefined values makes sure that
|
|
the corresponding attributes are left as-is.
|
|
</p>
|
|
<p>
|
|
Fields with undefined or uncertain values are declared as normal fields in a form, except they also have the
|
|
<strong>xdd:notSame</strong> flag present in the declaration, as is shown in the following example:
|
|
</p>
|
|
<example caption='Publishing fields with undefined values'>
|
|
<![CDATA[
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp:xdata:dynamic"
|
|
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
|
|
<title>Communication properties</title>
|
|
<field var='xdd session' type='hidden'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="Address" type="text-single" label="Bus Address:">
|
|
<desc>Enter the bus address of the device.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:int">
|
|
<xdv:range min="1" max="250"/>
|
|
</xdv:validate>
|
|
<value>1</value>
|
|
<xdd:notSame/>
|
|
</field>
|
|
<field var="BaudRate" type="list-single" label="Baud rate:">
|
|
<desc>Baud rate to use when communicating with the device.</desc>
|
|
<value>2400</value>
|
|
<option label='300 baud'><value>300</value></option>
|
|
<option label='2400 baud'><value>2400</value></option>
|
|
</field>
|
|
...
|
|
</x>]]>
|
|
</example>
|
|
<p>
|
|
In the above example communication properties of a set of objects are edited. The form contains two fields, one address field, which will contain
|
|
unique values for each individual object and therefore be flagged with the <strong>xdd:notSame</strong> flag, and
|
|
a second baud rate field. This second field will probably contain the same value, if devices are connected to the
|
|
same bus. Therefore, the field value is not flagged with the <strong>xdd:notSame</strong> flag.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> If the <strong>xdd:notSame</strong> flag is available in a field, the field must not be
|
|
flagged as being <strong>required</strong>. They must also be omitted in any form submissions unless they have been
|
|
edited first. Furthermore, any field submitted in a post-back as described in this document, must not be returned
|
|
in the post-back response having the <strong>xdd:notSame</strong> flag.
|
|
</p>
|
|
<p>
|
|
Notice also that there's a difference between a missing value, i.e. a field without a <strong>value</strong> element defined, and
|
|
a field with a <strong>value</strong> defined, but with the <strong>xdd:notSame</strong> flag present. In the latter example,
|
|
the value might represent the value of one of the objects in a set of objects being edited.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Publishing fields containing errors'>
|
|
<p>
|
|
A field can be flagged with an error message using the <strong>xdd:error</strong> element. Together with the post-back feature this allows
|
|
for more advanced server-side validation of field values, as is shown in the following example.
|
|
</p>
|
|
<example caption='Publishing fields with undefined values'>
|
|
<![CDATA[
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp:xdata:dynamic"
|
|
xmlns:xdv="http://jabber.org/protocol/xdata-validate">
|
|
<title>Expression</title>
|
|
<field var='xdd session' type='hidden'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
<field var="Expression" type="text-single" label="Expression:">
|
|
<desc>Enter the expression you want to plot.</desc>
|
|
<xdv:validate xmlns:xdv="http://jabber.org/protocol/xdata-validate" datatype="xs:string">
|
|
<xdv:basic/>
|
|
</xdv:validate>
|
|
<value>sin(x</value>
|
|
<xdd:postBack/>
|
|
<xdd:error>Unexpected end of expression. ) expected.</xdd:error>
|
|
</field>
|
|
...
|
|
</x>]]>
|
|
</example>
|
|
<p>
|
|
In the above example, the user can enter a script expression into a text box using a server-specific scripting language.
|
|
There's no way for the client to validate the script expression. However, by flagging the field with <strong>xdd:postBack</strong>
|
|
the client posts the form back to the server when the user is finished writing the expression, and the server can validate it.
|
|
In the example, the user has made an error, and the server returns the field, with an <strong>xdd:error</strong> flag, containing
|
|
an error message that can be displayed to the user in an appropriate way.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> If a field is flagged with an error, and the user starts editing it, the client should remove the error
|
|
flag of the field. The field can be flagged again with a new error flag during the next post-back.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Cancelling a dynamic form'>
|
|
<p>
|
|
The <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link> XEP provides a mechanism to cancel forms, by submitting the
|
|
form using <strong>type='cancel'</strong>. The <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link> XEP stipulates that
|
|
fields should not be included when using the form type cancel. However dynamic forms, i.e. forms containing post-back fields, will need
|
|
the fields, since any dynamic form session will be identified using hidden fields in the form. So, to cancel a dynamic form, the
|
|
<strong>xdd:cancel</strong> element with the entire submitted form should be sent to the form server using an IQ set stanza, as is shown
|
|
in the following example:
|
|
</p>
|
|
<example caption='Cancelling a dynamic form'>
|
|
<![CDATA[
|
|
<iq type='set'
|
|
from='formclient@example.org/client'
|
|
to='formserver@example.org'
|
|
id='4'>
|
|
<cancel xmlns='urn:xmpp:xdata:dynamic'>
|
|
<x xmlns="jabber:x:data" type="submit">
|
|
<field var='xdd session'>
|
|
<value>009c7956-001c-43fb-8edb-76bcf74272c9</value>
|
|
</field>
|
|
...
|
|
</x>
|
|
</cancel>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
After receiving the cancel request the form server returns an empty response if the form was found (and therefore cancelled), or an
|
|
IQ error stanza with an <strong>item-not-found</strong> error if the form was not found. The following example shows a response where
|
|
the form was found and cancelled:
|
|
</p>
|
|
<example caption='Dynamic form cancelled'>
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='formserver@example.org'
|
|
to='formclient@example.org/client'
|
|
id='4'/>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> If cancelling a dynamic form using the approach described in this document, there's no need to also submit
|
|
a cancel form as defined in the <link url='http://xmpp.org/extensions/xep-0004.html'>Data Forms</link> XEP. The form server automatically
|
|
makes sure the form is cancelled in all instances on the form server.
|
|
</p>
|
|
<p>
|
|
<strong>Note 2:</strong> If the dynamic form is invoked from a specific operation that includes its own cancel procedure, like
|
|
Ad-hoc command sessions, the dynamic form is automatically and implicitly cancelled if the corresponding operation is cancelled.
|
|
There is no need to explicitly cancel the dynamic form as explained in this section in such cases.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Dynamic form not found during post-back'>
|
|
<p>
|
|
It might happen that the form server does not find the dynamic form posted by the form client during a post back. Reasons for this can be
|
|
that the form does not include a post-back field, or that a form session timeout has occurred and the form server has discarded the dynamic
|
|
form to avoid memory leaks. Regardless of the reason, the form server responds using an IQ error stanza with the <strong>item-not-found</strong>
|
|
error, when the client posts a form that is not found back.
|
|
</p>
|
|
<example caption='Dynamic form not found during post-back'>
|
|
<![CDATA[
|
|
<iq type='error'
|
|
from='formserver@example.org'
|
|
to='formclient@example.org/client'
|
|
id='2'>
|
|
<error type='cancel'>
|
|
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
</error>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
<strong>Note:</strong> Form post-back must only be performed on forms containing post-back fields. The form server
|
|
is not required to maintain dynamic form sessions for forms that lack post-back fields.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Other error during post-back'>
|
|
<p>
|
|
If another error occurs during post-back, the form server can inform the client about this by using the relevant error element and
|
|
provide further information in a <strong>text</strong> element to describe the error, as is shown in the following example:
|
|
</p>
|
|
<example caption='Other error during post-back'>
|
|
<![CDATA[
|
|
<iq type='error'
|
|
from='formserver@example.org'
|
|
to='formclient@example.org/client'
|
|
id='3'>
|
|
<error type='cancel'>
|
|
<internal-server-error xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
|
|
<text>An internal error occurred: Stack limit has been reached.</text>
|
|
</error>
|
|
</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>updated</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>updated</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="urn:xmpp: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@example.org'
|
|
to='client@example.org/client'>
|
|
<updated xmlns='urn:xmpp:xdata:dynamic' sessionVariable='xdd session' xml:lang='en'>
|
|
<x xmlns="jabber:x:data" type="form"
|
|
xmlns:xdd="urn:xmpp: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>
|
|
</updated>
|
|
</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>
|
|
<p>
|
|
<strong>Note 2:</strong> The client should also provide the current user language in a <strong>xml:lang</strong> attribute in the <strong>updated</strong>
|
|
element, if available, as is shown in the example above.
|
|
</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
|
|
that fact by returning a feature of "urn:xmpp:xdata:dynamic" in response to &xep0030; information requests.</p>
|
|
<example caption="Service discovery information request">
|
|
<![CDATA[
|
|
<iq type='get'
|
|
from='formclient@example.org/client'
|
|
to='formserver@example.org'
|
|
id='disco1'>
|
|
<query xmlns='http://jabber.org/protocol/disco#info'/>
|
|
</iq>]]>
|
|
</example>
|
|
<example caption="Service discovery information response">
|
|
<![CDATA[
|
|
<iq type='result'
|
|
from='formserver@example.org'
|
|
to='formclient@example.org/client'
|
|
id='disco1'>
|
|
<query xmlns='http://jabber.org/protocol/disco#info'>
|
|
...
|
|
<feature var='urn:xmpp:xdata:dynamic'/>
|
|
...
|
|
</query>
|
|
</iq>]]>
|
|
</example>
|
|
<p>
|
|
In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic, presence-based profile of service discovery defined
|
|
in &xep0115;. However, if an application has not received entity capabilities information from an entity, it SHOULD use explicit service discovery instead.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='Implementation Notes' anchor='impl'>
|
|
<section2 topic='Dynamic Form Sessions'>
|
|
<p>
|
|
For a form server to maintain the status of the dynamic form, it will probably need to publish state or session
|
|
information using hidden fields in the dynamic form. It's important that form clients be aware that such hidden
|
|
fields are available and must always return them in all submissions of the form to the server.
|
|
</p>
|
|
<p>
|
|
A form client that supports dynamic forms and opens a dynamic form, i.e. containing parameters requiring post-back,
|
|
must call the specific <strong>cancel</strong> method described in this document to cancel the form if not
|
|
submitted. This to let the form server to release any dynamic form session resources it maintains.
|
|
</p>
|
|
<p>
|
|
<strong>Note:</strong> When submitting a dynamic form the normal way, any dynamic form session resources are also
|
|
automatically released.
|
|
</p>
|
|
</section2>
|
|
<section2 topic='Session Timeouts'>
|
|
<p>
|
|
The form server must be aware that some form clients do not support dynamic forms. This in turn implies that form clients
|
|
may not call the correct cancel method to cancel a dynamic form. To protect the form server from memory leaks, it must
|
|
include a session timeout, and release any dynamic form session resources if no activity has been made during the
|
|
corresponding time period. If the client would perform a post-back after the timeout period, an <strong>item-not-found</strong>
|
|
error message must be returned, to show the corresponding dynamic form session no longer exists, and therefore could
|
|
not be found.
|
|
</p>
|
|
<p>
|
|
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>
|
|
</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>
|
|
There are no security concerns related to this specification above, beyond those described in the relevant section of <strong>XMPP Core</strong>.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='IANA Considerations' anchor='iana'>
|
|
<p>This document requires no interaction with &IANA;.</p>
|
|
</section1>
|
|
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
|
|
<p>
|
|
The <link url="#schema">protocol schema</link> needs to be added to the list of <link url="http://xmpp.org/resources/schemas/">XMPP protocol schemas</link>.
|
|
</p>
|
|
</section1>
|
|
<section1 topic='XML Schema' anchor='schema'>
|
|
<code>
|
|
<![CDATA[
|
|
<?xml version='1.0' encoding='UTF-8'?>
|
|
<xs:schema
|
|
xmlns:xs='http://www.w3.org/2001/XMLSchema'
|
|
targetNamespace='urn:xmpp:xdata:dynamic'
|
|
xmlns='urn:xmpp:xdata:dynamic'
|
|
xmlns:xd="jabber:x:data"
|
|
elementFormDefault='qualified'>
|
|
|
|
<xs:import namespace='jabber:x:data'/>
|
|
|
|
<xs:element name='postBack'>
|
|
<xs:annotation>
|
|
<xs:documentation>Flags a field as requiring server post-back after having been edited.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType/>
|
|
</xs:element>
|
|
|
|
<xs:element name='readOnly'>
|
|
<xs:annotation>
|
|
<xs:documentation>Flags a field as being read-only.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType/>
|
|
</xs:element>
|
|
|
|
<xs:element name='notSame'>
|
|
<xs:annotation>
|
|
<xs:documentation>Flags a field as having an undefined or uncertain value.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:complexType/>
|
|
</xs:element>
|
|
|
|
<xs:element name='error'>
|
|
<xs:annotation>
|
|
<xs:documentation>Flags a field as having an error.</xs:documentation>
|
|
</xs:annotation>
|
|
<xs:simpleType>
|
|
<xs:restriction base='xs:string'/>
|
|
</xs:simpleType>
|
|
</xs:element>
|
|
|
|
<xs:element name='submit'>
|
|
<xs:complexType>
|
|
<xs:sequence>
|
|
<xs:element ref='xd:x' minOccurs='1' maxOccurs='1'/>
|
|
</xs:sequence>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:element name='updated'>
|
|
<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:element name='cancel'>
|
|
<xs:complexType>
|
|
<xs:sequence>
|
|
<xs:element ref='xd:x' minOccurs='1' maxOccurs='1'/>
|
|
</xs:sequence>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
</xs:schema>]]>
|
|
</code>
|
|
</section1>
|
|
<section1 topic='Acknowledgements' anchor='ack'>
|
|
<p>Thanks to Karin Forsell and Lance Stout for all valuable feedback.</p>
|
|
</section1>
|
|
</xep>
|