From 9aa9b1a8ce3104a3d7d5a282f126c51ecc877ce8 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt Date: Fri, 9 Dec 2016 12:37:28 -0700 Subject: [PATCH 01/11] cc -> introduction --- _sections/00-Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sections/00-Introduction.md b/_sections/00-Introduction.md index 547323f..ca6ed8e 100644 --- a/_sections/00-Introduction.md +++ b/_sections/00-Introduction.md @@ -4,6 +4,6 @@ title: Introduction The ODK XForm specification is a subset of the far larger [XForm 1.0 specification](http://www.w3.org/TR/xforms/). It contains a few additional features not found in the XForm specification. -The ODK XForm Specification continues to evolve. On the web you will often see references to _JavaRosa_ and _OpenRosa_ when the spec is discussed. OpenRosa was the name of the [initial specification](https://bitbucket.org/javarosa/javarosa/wiki/xform) that formed the basis of the ODK specification. JavaRosa is the name of a Java library that implements the OpenRosa specification. ODK, JavaRosa, OpenRosa are still often used to refer to the same, but we recommend using this document to build tools that are compliant with the ODK Ecosystem. +This specification continues to evolve. On the web you will often see references to _JavaRosa_ and _OpenRosa_ when the spec is discussed. OpenRosa was the name of the initial specification that formed the basis of this document. JavaRosa is a library that implements the XForm part of the OpenRosa specification. The document assumes at least a fair understanding of XML and XPath. It is also useful to refer to [XForms 1.0](http://www.w3.org/TR/2003/REC-xforms-20031014/) for details about shared features. From 3f531e99440a2bf7c35810fe3386fcc791f36d98 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt Date: Fri, 9 Dec 2016 15:37:58 -0700 Subject: [PATCH 02/11] cc -> structure, #22 --- _sections/10-structure.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/_sections/10-structure.md b/_sections/10-structure.md index f4c8748..151a5d2 100644 --- a/_sections/10-structure.md +++ b/_sections/10-structure.md @@ -9,16 +9,15 @@ The high-level form definition is structured as follows: * bindings * body -The model contains the **[instance](#instance)**(s) and the **[bindings](#bindings)**. The first instance is the XML data structure of the _record_ that is captured with the form. A binding describes an individual instance node and includes information such as _datatype, skip logic, calculations, and more_. +The model contains the **[instance](#instance)**(s) and the **[bindings](#bindings)**. The first instance is the XML data structure of the _record_ that is captured with the form. A binding describes an individual instance node and includes information such as _datatype, skip logic, calculations,_ and more. The **[body](#body)** contains the information required to _display_ a form. -Below is an example of a complete and valid ODK XForm: +Below is an example of a complete and valid XForm: {% highlight xml %} My Survey - + - - - + + + - - - + + + + @@ -54,3 +54,10 @@ Below is an example of a complete and valid ODK XForm: {% endhighlight %} + +Outside of this simplified structure there are ways to define: + +* form title as the `` element, a child of the `<head>` element, +* [linkages with external (mobile) applications](#external-applications), +* [language dictionaries](#languages). + From dde05f9938a29b2ad1279f14ebf9dd03fbff7833 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Fri, 9 Dec 2016 15:45:46 -0700 Subject: [PATCH 03/11] cc -> templates, style --- _includes/footer.html | 6 ------ css/main.css | 25 +++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/_includes/footer.html b/_includes/footer.html index 22c4a4b..e5e070d 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -20,9 +20,3 @@ </div> </footer> -<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> -<script> -$(document).ready(function(){ - $(".post-content > ul:first-child").appendTo(".sidenav"); -}); -</script> diff --git a/css/main.css b/css/main.css index 6c7e3aa..347a612 100644 --- a/css/main.css +++ b/css/main.css @@ -164,6 +164,7 @@ table tr th, table tr td { .footer-col-1 { width: 270px; + /*fallback*/ width: -webkit-calc(35% - 10px); width: -moz-calc(35% - 10px); @@ -174,6 +175,7 @@ table tr th, table tr td { .footer-col-2 { width: 175px; + /*fallback*/ width: -webkit-calc(23.125% - 10px); width: -moz-calc(23.125% - 10px); @@ -184,6 +186,7 @@ table tr th, table tr td { .footer-col-3 { width: 335px; + /*fallback*/ width: -webkit-calc(41.875%); width: -moz-calc(41.875%); @@ -317,8 +320,8 @@ table tr th, table tr td { .post pre, .post code { - border: 1px solid #d5d5e9; - background-color: #eef; + border: 1px solid #ccc; + background-color: #fcfcfc; padding: 8px 12px; -webkit-border-radius: 3px; -moz-border-radius: 3px; @@ -706,14 +709,18 @@ table tr th, table tr td { .wrap { width: 100%; } + .sidenav { width: 100%; } + .footer-col-1 { width: 50%; } + .footer-col-2 { width: 45%; + /*fallback*/ width: -webkit-calc(50% - 10px); width: -moz-calc(50% - 10px); @@ -721,6 +728,7 @@ table tr th, table tr td { width: calc(50% - 10px); margin-right: 0; } + .site-footer .column.footer-col-3 { width: auto; float: none; @@ -732,6 +740,7 @@ table tr th, table tr td { .wrap { padding: 0 12px; } + .site-nav { position: fixed; z-index: 10; @@ -743,6 +752,7 @@ table tr th, table tr td { border-radius: 5px; border: 1px solid #e8e8e8; } + .site-nav .menu-icon { display: block; font-size: 24px; @@ -752,18 +762,22 @@ table tr th, table tr td { text-align: center; line-height: 36px; } + .site-nav .menu-icon svg { width: 18px; height: 16px; } + .site-nav .trigger { clear: both; margin-bottom: 5px; display: none; } + .site-nav:hover .trigger { display: block; } + .site-nav .page-link { display: block; text-align: right; @@ -771,25 +785,32 @@ table tr th, table tr td { padding: 5px 10px; margin: 0; } + .post-header h1 { font-size: 36px; } + .post-content h2 { font-size: 28px; } + .post-content h3 { font-size: 22px; } + .post-content h4 { font-size: 18px; } + .post-content blockquote { padding-left: 10px; } + .post-content ul, .post-content ol { padding-left: 10px; } + .site-footer .column { float: none; clear: both; From e3c8cc857b3557fd09d8169c07b77deeaa724e09 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Fri, 9 Dec 2016 16:01:30 -0700 Subject: [PATCH 04/11] cc -> instance --- _sections/20-instance.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/_sections/20-instance.md b/_sections/20-instance.md index e5f539a..afb1f81 100644 --- a/_sections/20-instance.md +++ b/_sections/20-instance.md @@ -10,7 +10,7 @@ The primary instance should contain a single childnode. In the example below `<h {% highlight xml %} <instance> - <household id="mysurvey" version="2014083101"> + <household id="mysurvey" orx:version="2014083101"> <person> <firstname/> <lastname/> @@ -23,22 +23,24 @@ The primary instance should contain a single childnode. In the example below `<h </instance> {% endhighlight %} -Any value inside a primary instance is considered a default value for that question. If that node has a corresponding input element that value will be displayed to the user when the question is parsed. +Any value inside a primary instance is considered a default value for that question. If that node has a corresponding input element that value will be displayed to the user when the question is rendered. Nodes inside a primary instance can contain attributes. The client application normally retains the attribute when a record is submitted. There are 3 pre-defined instance attributes: | attribute | description |---------------|------------ -| `id` | on the childnode of the primary instance: This is the unique ID at which the form is identified the server that publishes the Form and receives data submissions. For more information see [this Form List Specification](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI). -| `version` | on the childnode of the primary instance can contain any string value. -| `jr:template` | on any repeat group node: This serves to define a default template for repeats and is useful if any of the leaf nodes inside a repeat contains a default value. It is not transmitted in the record. For more details, see the [repeats](#repeats) section. +| `id` | on the childnode of the primary instance: This is the unique ID at which the form is identified the server that publishes the Form and receives data submissions. For more information see [this Form List Specification](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI). \[required\] +| `orx:version` | on the childnode of the primary instance in the _http://openrosa.org/xforms/_ namespace: Form version which can contain any string value. Like [meta nodes](#metadata) this information is used as a _processing cue_ for the server receiving the submission. +| `jr:template` | on any repeat group node in the _http://openrosa.org/javarosa namespace_: This serves to define a default template for repeats and is useful if any of the leaf nodes inside a repeat contains a default value. It is not transmitted in the record and only affects the behavior of the form engine. For more details, see the [repeats](#repeats) section. + +The primary instance also includes a special type of nodes for metadata inside the `<meta>` block. See the [Metadata](#metadata) section + -The primary instance also includes a special type of nodes for metadata inside the `<meta>` block. [pending]() - See the [Metadata](#preloaders---metadata) section -### Secondary Instances +### Secondary Instances - Internal -Secondary instances are used to pre-load data inside a form. This data is searchable in XPath. At the moment the only use case is so-called _cascading selections_ where the available options of a multiple-choice question can be filtered based on an earlier answer. +Secondary instances are used to pre-load read-only data inside a form. This data is searchable in XPath. At the moment the key use case is in designing so-called _cascading selections_ where the available options of a multiple-choice question can be filtered based on an earlier answer. A secondary instance should get a unique `id` attribute on the `<instance>` node. This allows apps to query the data (which is outside the root, ie. the primary instance, and would normally not be reachable). It uses the the `instance('cities')/root/item[country='nl']` syntax to do this. From ccb6acba0d93344b766240c7a86286f77decc6c9 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Fri, 9 Dec 2016 16:14:02 -0700 Subject: [PATCH 05/11] cc -> bindings #43 (partial), closes #30, closes #29, closes #28, closes #26, closes #19 --- _sections/30-bindings.md | 85 +++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/_sections/30-bindings.md b/_sections/30-bindings.md index e298e1b..abb11f2 100644 --- a/_sections/30-bindings.md +++ b/_sections/30-bindings.md @@ -4,6 +4,8 @@ title: Bindings A `<bind>` element wires together a primary instance node and the presentation of the corresponding question to the user. It is used to describe the datatype and various kinds of logic related to the data. A bind can refer to any node in the primary instance including repeated nodes_. It may or may not have a corresponding presentation node in the [body](#body). +An instance node does not require a corresponding `<bind>` node, regardless of whether it has a presentation node. + {% highlight xml %} <bind nodeset="/d/my_intro" type="string" readonly="true()"/> <bind nodeset="/d/text_widgets/my_string" type="string"/> @@ -31,12 +33,12 @@ The following attributes are supported on `<bind>` nodes. Only the nodeset attri | attribute | description | | --------- | --------- | -| `nodeset` | Specifies the [path](#xpath-paths) to the instance node' \[required\]. -| `type` | Specifies the data type. These are discussed below. Considered string if omitted. -| `readonly` | Specifies whether the user is allowed to enter data, options: `true()`, and `false()`. Considered false() if omitted. -| `required` | Specifies whether the question requires a non-empty value, options: `true()`, and `false()`. Considered false() if omitted. -| `relevant` | Specifies whether the question or group is relevant. The question or group will only be presented to the user when the XPath expression evaluates to true. When false the data node (and their descendants) is/are emptied. -| `constraint`| Specifies acceptable answers for the specified prompt with an XPath expression. +| `nodeset` | Specifies the [path](#xpath-paths) to the instance node or attribute \[required\]. +| `type` | Specifies the data type. These are discussed below. Considered "string" if omitted or if an unknown type is provided. +| `readonly` | Specifies whether the user is allowed to enter data, using a boolean expression. Considered `false()` if omitted. +| `required` | Specifies whether the question requires a non-empty value, using a boolean expression. Considered `false()` if omitted. +| `relevant` | Specifies whether the question or group is relevant. The question or group will only be presented to the user when the XPath expression evaluates to `true()`. When `false()` the data node (and its descendants) are removed from the primary instance on submission. +| `constraint`| Specifies acceptable answers for the specified prompt with an XPath expression. Will only be evaluated when the node is non-empty. | `calculate` | Calculates a node value with an XPath expression. | `saveIncomplete` | Specifies whether to automatically save the draft record when the user reaches this question, options `true()` and `false()`. Considered false() if omitted. | `jr:constraintMsg` | The message that will be displayed if the specified constraint is violated. @@ -47,20 +49,19 @@ The following attributes are supported on `<bind>` nodes. Only the nodeset attri | type | description |------------|------------ -| `string` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#string) -| `int` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#int) -| `boolean` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#boolean) -| `decimal` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#decimal) -| `date` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#date) -| `time` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#time) -| `dateTime` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#dateTime) [review]() -| `select` | space-separated list of strings [review]() -| `select1` | as string (spaces strongly discouraged) [review]() -| `geopoint` | space-separated list of valid latitude (decimal degrees), longitude (decimal degrees), altitude (decimal meters) and accuracy (decimal meters) -| `geotrace` | semi-colon separated list of at least 2 geopoints, where the last geopoint's latitude and longitude is not equal to the first -| `geoshape` | semi-colon separated list of at least 3 geopoints, where the last geopoint's latitude and longitude is equal to the first -| `binary` | [review]() -| `barcode` | as string [review]() +| `string` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#string), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `int` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#int), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `boolean` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#boolean), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `decimal` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#decimal), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `date` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#date), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `time` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#time), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `dateTime` | As in [XML 1.0](http://www.w3.org/TR/xmlschema-2/#dateTime), optionally in "http://www.w3.org/2001/XMLSchema" namespace +| `geopoint` | Space-separated list of valid latitude (decimal degrees), longitude (decimal degrees), altitude (decimal meters) and accuracy (decimal meters) +| `geotrace` | Semi-colon-separated list of at least 2 geopoints, where the last geopoint's latitude and longitude is not equal to the first +| `geoshape` | Semi-colon-separated list of at least 3 geopoints, where the last geopoint's latitude and longitude is equal to the first +| `binary` | String ID (with binary file attached to submission) +| `barcode` | As string +| `intent` | As string, used for [external applications](#declaring-external-application) ### XPath Paths @@ -79,31 +80,30 @@ The following are examples of valid paths: * `//node` -### XPath Expressions +### XPath Operators -All [XPath 1.0 expressions](http://www.w3.org/TR/xpath/#section-Expressions) are supported, i.e. `|`, `or`, `and`, `=`, `!=`, `<=`, `<`, `>=`, `>`. Note that predicate support is very limited (see next section). +All [XPath 1.0 operators](http://www.w3.org/TR/xpath/#exprlex) are supported, i.e. `|`, `and`, `or`, `mod`, `div`, `=`, `!=`, `<=`, `<`, `>=`, `>`. ### XPath Predicates -Only the `path/to[node=value]` predicate is supported. - -\[What about `xpath/to/node[2]`, `xpath/to/node[@attr=value]`, `xpath/to/node[position()=2]` in JavaRosa?. [review]()\] +Predicates are fully supported but with the limitations described in [XPath Axes](#xpath-axes) and [XPath Functions](#xpath-functions) ### XPath Axes -Only the _parent_ and _child_ axes are supported of the [XPath 1.0 axes](https://developer.mozilla.org/en-US/docs/Web/XPath/Axes). [review]() +Only the _parent_, _child_ and _self_ axes are supported of the [XPath 1.0 axes](https://developer.mozilla.org/en-US/docs/Web/XPath/Axes). ### XPath Functions A subset of [XPath 1.0 functions](http://www.w3.org/TR/xpath/#corelib), some functions of later versions of XPath, and a number of additional custom functions are supported. Some of the XPath 1.0 functions have been extended with additional functionality. -| function | description | -|---------|------| +| function | description | +|-------------------------------------------|------| | `concat(* arg*)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-concat) in that it may contain _1 argument_ and that all arguments can be _nodesets_ or strings. It concatenates all string values and _all node values_ inside the provided nodesets. | `selected(string list, string value)` | Checks if value is equal to an item in a space-separated list (e.g. `select` data type values). -| `selected-at(string list, int index)` | Returns the value of the item at the 1-based index of a space-separated list or empty string if the item does not exist (including for negative index and index 0). +| `selected-at(string list, int index)` | Returns the value of the item at the 0-based index of a space-separated list or empty string if the item does not exist (including for negative index and index 0). | `count-selected(string list)` | Returns the number of items in a space-separated list (e.g. `select` data type values). | `jr:choice-name(string value, node node)` | Returns the label value in the active language corresponding to the choice option with the given value of a select or select1 question question for the given data node. (sorry) +| `jr:itext(string arg)` | Obtains an itext value for the provided reference in the active language. | `indexed-repeat(nodeset arg, nodeset repeat1, int index1, [nodeset repeatN, int indexN]{0,2})` | Returns a single node from a nodeset by selecting the 0-based index of a repeat nodeset. It does this up to 3 repeat levels deep. | `true()` | As in [XPath 1.0](http://www.w3.org/TR/xpath/#section-Boolean-Functions). | `false()` | As in [XPath 1.0](http://www.w3.org/TR/xpath/#section-Boolean-Functions). @@ -125,22 +125,25 @@ A subset of [XPath 1.0 functions](http://www.w3.org/TR/xpath/#corelib), some fun | `string-length(string arg)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-string-length) in that the argument is _required_. | `count(nodeset arg)` | As in [XPath 1.0](http://www.w3.org/TR/xpath/#function-count). | `sum(nodeset arg)` | As in [XPath 1.0](http://www.w3.org/TR/xpath/#function-sum). -| `max(nodeset arg*)` | As in [XPath 2.0](http://www.w3.org/TR/xpath-functions/#func-max). [pending](https://code.google.com/p/opendatakit/issues/detail?id=1044) -| `min(nodeset arg*)` | As in [XPath 2.0](http://www.w3.org/TR/xpath-functions/#func-min). [pending](https://code.google.com/p/opendatakit/issues/detail?id=1044) -| `round(number arg, number decimals?)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-round) in that a second argument may be provided to specify the number of decimals. [pending](https://code.google.com/p/opendatakit/issues/detail?id=1045) +| `max(nodeset arg*)` | As in [XPath 2.0](http://www.w3.org/TR/xpath-functions/#func-max). +| `min(nodeset arg*)` | As in [XPath 2.0](http://www.w3.org/TR/xpath-functions/#func-min). +| `round(number arg, number decimals?)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-round) in that a second argument may be provided to specify the number of decimals. | `pow(number value, number power)` | As in [XPath 3.0](http://www.w3.org/TR/xpath-functions-30/#func-math-pow). -| `today()` | Returns today's datetime as a string [review]() -| `now()` | same as today() [review]() -| `random()` | Returns a random number between 0.0 (inclusive) and 1.0 (exclusive) -| `uuid()` | Return a random [RFC 4122 version 4](http://tools.ietf.org/html/rfc4122) compliant UUID string [review]() +| `log(number arg)` | As in [XPath 3.0](http://www.w3.org/TR/xpath-functions-30/#func-math-log). +| `log10(number arg)` | As in [XPath 3.0](http://www.w3.org/TR/xpath-functions-30/#func-math-log10). +| `today()` | Returns today's date without a time component. +| `now()` | Returns the current datetime in the current time zone. +| `random()` | Returns a random number between 0.0 (inclusive) and 1.0 (exclusive). +| `depend(* arg*)` | Returns first argument. Shouldn't need to be used. +| `uuid(number?)` | Without arguments, it returns a random [RFC 4122 version 4](http://tools.ietf.org/html/rfc4122) compliant UUID. With an argument it returns a random GUID with the provided number of characters. | `checklist(number min, number max, string v*)` | Check wether the count of answers that evaluate to true (when it converts to a number > 0) is between the minimum and maximum inclusive. Min and max can be -1 to indicate _not applicable_. | `weighted-checklist(number min, number max, [string v, string w]*)` | Like checklist(), but the number of arguments has to be even. Each v argument is paired with a w argument that _weights_ each v (true) count. The min and max refer to the weighted totals. -| `position(node arg?)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-position) in that it accepts an argument. This argument has to be a single node. If an argument is provided the function returns the position of that node amongst its siblings (with the same node name). [review]() -| `property(string prop)` | Tbd, this is **not** a valid XPath function in its current JavaRosa implementation. [pending](https://code.google.com/p/opendatakit/issues/detail?id=1034) -| `instance(string id)` | Returns a [secondary instance](#secondary-instances) node with the provided id, e.g. `instance('cities')/item/[country=/data/country]`. It is the only way to refer to a node outside of the primary instance. Note that it doesn't switch the XML Document (the primary instance) or document root for other expressions. E.g. `/data/country` still refers to the primary instance. -| `current()` | In the same league as `instance(ID)` but always referring to the primary instance (and accepting no arguments). Unlike instance(ID), which always requires an absolute path, current() can be used with relative references (e.g. `current()/.` and `current()/..`). +| `position(node arg?)` | Deviates from [XPath 1.0](http://www.w3.org/TR/xpath/#function-position) in that it accepts an argument. This argument has to be a single node. If an argument is provided the function returns the position of that node amongst its siblings (with the same node name). +| `property(string prop)` | Tbd +| `instance(string id)` | Returns a [secondary instance](#secondary-instances) node with the provided id, e.g. `instance('cities')/item/[country=/data/country]`. It is the only way to refer to a node outside of the primary instance. Note that it doesn't switch the XML Document (the primary instance) or document root for other expressions. E.g. `/data/country` still refers to the primary instance. +| `current()` | In the same league as `instance(ID)` but always referring to the primary instance (and accepting no arguments). Unlike instance(ID), which always requires an absolute path, current() can be used with relative references (e.g. `current()/.` and `current()/..`). | `area(node-set ns | geoshape gs)` | Returns the calculated area in m2 of either a nodeset of geopoints or a geoshape value (not a combination of both) on Earth. It takes into account the circumference of the Earth around the Equator but does not take altitude into account. -| `once(* calc)` | The parameter will be returned if the context nodes's value is empty, otherwise the current value of the context node will be returned. The function is used e.g. to ensure that a random number is only generated once with `once(random())`. [review]() +| `once(* calc)` | The parameter will be evaluated and returned if the context nodes's value is empty, otherwise the current value of the context node will be returned. The function is used e.g. to ensure that a random number is only generated once with `once(random())`. ### Preloaders - Metadata From f25b07df49cd00c271a693b24569be8752153eea Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Fri, 9 Dec 2016 16:49:57 -0700 Subject: [PATCH 06/11] cc -> body --- _sections/40-body.md | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/_sections/40-body.md b/_sections/40-body.md index 3945094..cd144a0 100644 --- a/_sections/40-body.md +++ b/_sections/40-body.md @@ -28,21 +28,43 @@ The following form control elements are supported: |`<select1>` | Used to display a single-select list (data type: select1) |`<select>` | Used to display a multiple-select list (data type: select) |`<upload>` | Used for image, audio, and video capture -|`<trigger>` | Used to obtain user confirmation (e.g. by displaying a single tickbox or button). Will add value _"OK"_ to corresponding instance node when user confirms. If not confirmed the value remains empty. [review]() +|`<trigger>` | Used to obtain user confirmation (e.g. by displaying a single tickbox or button). Will add value _"OK"_ to corresponding instance node when user confirms. If not confirmed the value remains empty. -Within the user controls the following elements can be used: +The following user interface elements are supported: | element | description -|---------------|------------------ +|---------------|--------------------------------------- | `<group>` | Child of `<body>`, another `<group>`, or a `<repeat>` that groups form controls together. See [groups](#groups) section for further details. | `<repeat>` | Child of `<body>` or `<group>` that can be repeated. See [repeats](#repeats) for further details. + +Within the form controls the following elements can be used: + +| element | description +|---------------|------------------ | `<label>` | Child of a [form control](#body-elements) element, `<item>`, `<itemset>` or `<group>` used to display a label. Only 1 `<label>` per form control is properly supported but can be used in [multiple languages](#languages)). | `<hint>` | Child of a [form control](#body-elements) element used to display a hint. Only 1 `<hint>` element per form control is properly supported but can be used in [multiple languages](#languages)). -| `<output>` | Child of a `<label>` or `<hint>` element used to display an instance value. +| `<output>` | Child of a `<label>` or `<hint>` element used to display an instance value, inline, as part of the label, or hint stext. | `<item>` | Child of `<select>` or `<select1>` that defines an choice option. | `<itemset>` | Child of `<select>` or `<select1>` that defines a list of choice options to be obtained elsewhere (from a [secondary instance](#secondary-instances)). | `<value>` | Child of `<item>` or `<itemset>` that defines a choice value. +Below is an example of a labels, an output, a hint, an itemset and value used together to define a form control: + +{% highlight xml %} + <group ref="/data/loc"> + <label>Location</label> + ... + <select1 ref="/data/loc/city"> + <label>City</label> + <hint>Cities in <output value="/data/loc/country"/></hint> + <itemset nodeset="instance('cities')/root/item[country= /data/loc/country ]"> + <value ref="name"/> + <label ref="label"/> + </itemset> + </select1> +</group> +{% endhighlight %} + ### Body Attributes The following attributes are supported on body elements. Note that most attributes can only be used on specific elements. If such a specific attribute is used on elements that do not support it, it will usually be silently ignored. @@ -56,10 +78,14 @@ The following attributes are supported on body elements. Note that most attribut | `jr:noAddRemove`| For the `<repeat>` element (see [repeats](#repeats)). This indicates whether the user is allowed to add or remove repeats. Can have values `true()` and `false()` | `autoplay` | For all 5 form control elements, this automatically plays a [video or audio 'label'](#media) if the question is displayed on its own page, when the user reaches this page. | `accuracyThreshold` | For `<input>` with type `geopoint`, `geotrace`, or `geoshape` this sets the auto-accept threshold in meters for geopoint captures. [review]() -| `rows` | Specifies the minimum number of rows a string `<input>` field gets in ODK Collect. In Enketo a similar effect is achieved by adding appearance="multiline". [pending](https://github.com/enketo/enketo-xslt/issues/26) +| `value` | For the `<output>` element to reference the node value to be displayed. +| `rows` | Specifies the minimum number of rows a string `<input>` field gets. + ### Appearances -The appearance of the 5 form controls can be changed with the appearance attributes. Appearance values usually relate to a specific [data type](#data-types). See the [XLS Form specification](http://xlsform.org) for a list of appearance attributes are available for each data type. Multiple space-separated appearance values can be added to a form control +The appearance of the 5 form controls can be changed with appearance attributes. Appearance values usually relate to a specific [data](#data-types) or [question](#body-elements) type. See the [XLS Form specification](http://xlsform.org) for a list of appearance attributes are available for each data type. Multiple space-separated appearance values can be added to a form control in any order. + +An appearance attribute can also be used to indicate that an [external app](#external-applications) should be used as a form control. + -TO ADD: 3rd party app launching with an appearance [review]() From ac366329d3d7f88980f55f26f678e4bfc1fb1308 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Mon, 12 Dec 2016 11:48:38 -0700 Subject: [PATCH 07/11] cc -> repeats --- _sections/60-repeats.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/_sections/60-repeats.md b/_sections/60-repeats.md index 2293499..cf4625d 100644 --- a/_sections/60-repeats.md +++ b/_sections/60-repeats.md @@ -6,6 +6,8 @@ Repeats are sections that may be repeated in a form. They could consist of a sin A `<repeat>` uses the nodeset attribute to identify which instance node (and its children) can be repeated. +A `<repeat>` cannnot have a label child element. To display a label it should be wrapped inside a `<group>` as shown below: + {% highlight xml %} ... <h:head> @@ -43,7 +45,7 @@ A `<repeat>` uses the nodeset attribute to identify which instance node (and its ### Creation, Removal of Repeats -The default behaviour of repeats is to let the user create or remove repeats using the the user interface. ODK Collect will ask for the first repeat. Enketo will show the first repeat automatically. This can be disabled by adding the attribute `jr:noAddRemove="true()"` to the `<repeat>` element. +The default behaviour of repeats is to let the user create or remove repeats using the the user interface. The user control for creating and removing repeats can be disabled by adding the attribute `jr:noAddRemove="true()"` to the `<repeat>` element. There are 2 different ways to ensure that multiple repeats are automatically created when a form loads. @@ -145,7 +147,7 @@ B. Specify the values for each repeat instance individually in the primary insta In XForms, relative XPaths should be evaluated _relative to context_, and absolute paths (/data/path/to/repeat) should be evaluated as _absolute paths without considering context_. If there are multiple repeats, the XPath /data/path/to/repeat would either return the first repeat (if e.g. a string value is requested), or all repeats (if a nodeset is requested). -However, in this spec, due to an unfortunate persistent historical error, **absolute paths** /data/path/to/repeat/node **inside repeats are always evaluated as if they are relative to the current nodeset**. In other words, the absolute XPath `/data/path/to/repeat/node` when it is referred to from inside a repeat is evaluated as if it is the relative XPath `../node`. +However, in this spec, due to an unfortunate persistent historical error, **absolute paths inside repeats are always evaluated as if they are relative to the current nodeset**. In other words, the absolute XPath `/data/path/to/repeat/node` when it is referred to from inside a repeat is evaluated as if it is the relative XPath `../node`. -_In order to rectify this error at some time in the future, it would be very helpful if any form builders around this spec [start generating relative references](https://github.com/SEL-Columbia/pyxform/issues/91) automatically._ +_In order to rectify this error at some time in the future, it would be very helpful if any form builders around this spec start generating relative references automatically._ From c0fcec7120388a656922e0eaeb325db0c98f2181 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Mon, 12 Dec 2016 12:10:58 -0700 Subject: [PATCH 08/11] cc -> languages --- _sections/70-languages.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/_sections/70-languages.md b/_sections/70-languages.md index 3d1af02..183c422 100644 --- a/_sections/70-languages.md +++ b/_sections/70-languages.md @@ -2,7 +2,7 @@ title: Languages --- -Multi-lingual content for labels, and hints is supported. This is optional and can be done by replacing all language-dependent strings with 'text identifiers', which act as indexes into a multi-lingual dictionary in the model. +Multi-lingual content for labels, and hints is supported. This is optional and can be done by replacing all language-dependent strings with 'text identifiers', which act as indexes into a multi-lingual dictionary in the model. The language strings can be identified with the `jr:itext()` [XPath function](#xpath-functions). In the `<model>`, a multi-lingual dictionary has the following structure: @@ -53,8 +53,14 @@ With the corresponding entries in `<itext>`: Not every string must be localized. It is acceptable to intermix `<label>`s of both forms. Those which do not reference the dictionary will always show the same content, regardless of language. +It is even allowed to intermix both a `ref` and a regular value. In this case, if the itext engine is missing it will refer to the regular value. E.g. + +{% highlight xml %} +<label ref="jr:itext('mykey')">a default value</label> +{% endhighlight %} + In general, all text ids must be replicated across all languages. It is sometimes only a parser warning if you do not, but it will likely lead to headaches. -Even within a single language, it is helpful to have multiple 'forms' of the same string. For example, a verbose phrasing used as the caption when answering a question, but a short, terse phrasing when that question is shown in the form summary. We handle this as follows: [review]() +Even within a single language, it is helpful to have multiple 'forms' of the same string. For example, a verbose phrasing used as the caption when answering a question, but a short, terse phrasing when that question is shown in the form summary. This can be done as follows: {% highlight xml %} <text id="how-old"> @@ -63,4 +69,11 @@ Even within a single language, it is helpful to have multiple 'forms' of the sam </text> {% endhighlight %} -The different `forms` are only supported for question captions (`<label>`s inside user controls). The [media](#media) section describes how to add non-text form labels using the same method. +There are two form attribute options for text strings: + +| text type | form attribute +|-----------------|----------------| +| single version | _no form attr_ | +| short version | `short` | + +The different `forms` are only supported for question captions (`<label>`s inside user controls). The [media](#media) section describes how to add non-text form labels in a similar manner. From 15812505ef110d611318076aa63407c711d5c910 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Mon, 12 Dec 2016 12:54:00 -0700 Subject: [PATCH 09/11] cc -> media --- _sections/80-media.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_sections/80-media.md b/_sections/80-media.md index 20008ad..24b038d 100644 --- a/_sections/80-media.md +++ b/_sections/80-media.md @@ -2,7 +2,7 @@ title: Media --- -The `<itext>` method described in the [languages](#languages) section can also be used for **media labels**. Media labels can be used in addition to text labels or instead of text labels. +The `<itext>` element described in the [languages](#languages) section can also be used for **media labels**. Media labels can be used in addition to text labels or instead of text labels. {% highlight xml %} .... From 378fc15eb5934736ef03d49f88fb2dffef6ba938 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Mon, 12 Dec 2016 14:34:12 -0700 Subject: [PATCH 10/11] cc -> uri + removed sections, closes #33 --- _sections/89-future.md | 9 --------- _sections/90-apps.md | 8 -------- _sections/90-uri.md | 15 +++++++++++++++ _sections/99-acknowledgements.md | 5 ----- 4 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 _sections/89-future.md delete mode 100644 _sections/90-apps.md create mode 100644 _sections/90-uri.md delete mode 100644 _sections/99-acknowledgements.md diff --git a/_sections/89-future.md b/_sections/89-future.md deleted file mode 100644 index 6b850b7..0000000 --- a/_sections/89-future.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Future ---- - -The following desired future features have been identified. - -* support for external data to create itemsets (like a [secondary instance](#secondary-instances) but loaded from an external source) -* a way to specify a slider widget with min, max and step for numerical inputs -* a better way to record and retrieve [metadata](#preloaders---metadata) diff --git a/_sections/90-apps.md b/_sections/90-apps.md deleted file mode 100644 index 6dc7a90..0000000 --- a/_sections/90-apps.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Apps ---- - -These are two examples of data collection applications and libraries that are conforming to this specification: - -* [Enketo Core](https://github.com/enketo/enketo-core) -* [ODK Collect](https://code.google.com/p/opendatakit/source/browse?repo=collect) diff --git a/_sections/90-uri.md b/_sections/90-uri.md new file mode 100644 index 0000000..62c2dd2 --- /dev/null +++ b/_sections/90-uri.md @@ -0,0 +1,15 @@ +--- +title: URI Support +--- + +Throughout the XForm format URIs are used to refer to resources outside of the XForm itself. The `jr` "protocol" is used to indicate the resource is available in a sandboxed environment the client is aware of. At the moment only binary endpoints are supported. + +### Binary Endpoints + +Binary endpoints point to files. The following are supported: + +| URI format | description +|--------------------------------------------|---------------- +| `jr://images/path/to/file.png` | points to an image resource in the sandboxed environment +| `jr://audio/path/to/file.mp3` | points to an audio resource in the sandboxed environment +| `jr://video/path/to/file.mp4` | points to a video resource in the sandboxed environment diff --git a/_sections/99-acknowledgements.md b/_sections/99-acknowledgements.md deleted file mode 100644 index 4542164..0000000 --- a/_sections/99-acknowledgements.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Acknowledgements ---- - -The [JavaRosa XForms document](https://bitbucket.org/javarosa/javarosa/wiki/xform) maintained by Dimagi formed the basis of this document. From e6c0d673213428a7ef264f55708509069b99d094 Mon Sep 17 00:00:00 2001 From: Martijn van de Rijdt <martijn@enketo.org> Date: Thu, 22 Dec 2016 13:22:27 -0700 Subject: [PATCH 11/11] cc -> final edits --- _sections/20-instance.md | 6 +++++- _sections/30-bindings.md | 2 +- _sections/40-body.md | 6 +++--- _sections/60-repeats.md | 2 +- _sections/95-future.md | 5 +++++ 5 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 _sections/95-future.md diff --git a/_sections/20-instance.md b/_sections/20-instance.md index afb1f81..772ec2b 100644 --- a/_sections/20-instance.md +++ b/_sections/20-instance.md @@ -29,7 +29,7 @@ Nodes inside a primary instance can contain attributes. The client application n | attribute | description |---------------|------------ -| `id` | on the childnode of the primary instance: This is the unique ID at which the form is identified the server that publishes the Form and receives data submissions. For more information see [this Form List Specification](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI). \[required\] +| `id` | on the childnode of the primary instance: This is the unique ID at which the form is identified by the server that publishes the Form and receives data submissions. For more information see [this Form List Specification](https://bitbucket.org/javarosa/javarosa/wiki/FormListAPI). \[required\] | `orx:version` | on the childnode of the primary instance in the _http://openrosa.org/xforms/_ namespace: Form version which can contain any string value. Like [meta nodes](#metadata) this information is used as a _processing cue_ for the server receiving the submission. | `jr:template` | on any repeat group node in the _http://openrosa.org/javarosa namespace_: This serves to define a default template for repeats and is useful if any of the leaf nodes inside a repeat contains a default value. It is not transmitted in the record and only affects the behavior of the form engine. For more details, see the [repeats](#repeats) section. @@ -110,3 +110,7 @@ A secondary instance should get a unique `id` attribute on the `<instance>` node </root> </instance> {% endhighlight %} + +### Secondary Instances - External + +[Proposal pending](https://github.com/opendatakit/odk-xform-spec/issues/50). diff --git a/_sections/30-bindings.md b/_sections/30-bindings.md index abb11f2..5ab17c0 100644 --- a/_sections/30-bindings.md +++ b/_sections/30-bindings.md @@ -2,7 +2,7 @@ title: Bindings --- -A `<bind>` element wires together a primary instance node and the presentation of the corresponding question to the user. It is used to describe the datatype and various kinds of logic related to the data. A bind can refer to any node in the primary instance including repeated nodes_. It may or may not have a corresponding presentation node in the [body](#body). +A `<bind>` element wires together a primary instance node and the presentation of the corresponding question to the user. It is used to describe the datatype and various kinds of logic related to the data. A bind can refer to any node in the primary instance including repeated nodes. It may or may not have a corresponding presentation node in the [body](#body). An instance node does not require a corresponding `<bind>` node, regardless of whether it has a presentation node. diff --git a/_sections/40-body.md b/_sections/40-body.md index cd144a0..bcc6b52 100644 --- a/_sections/40-body.md +++ b/_sections/40-body.md @@ -43,12 +43,12 @@ Within the form controls the following elements can be used: |---------------|------------------ | `<label>` | Child of a [form control](#body-elements) element, `<item>`, `<itemset>` or `<group>` used to display a label. Only 1 `<label>` per form control is properly supported but can be used in [multiple languages](#languages)). | `<hint>` | Child of a [form control](#body-elements) element used to display a hint. Only 1 `<hint>` element per form control is properly supported but can be used in [multiple languages](#languages)). -| `<output>` | Child of a `<label>` or `<hint>` element used to display an instance value, inline, as part of the label, or hint stext. +| `<output>` | Child of a `<label>` or `<hint>` element used to display an instance value, inline, as part of the label, or hint text. | `<item>` | Child of `<select>` or `<select1>` that defines an choice option. | `<itemset>` | Child of `<select>` or `<select1>` that defines a list of choice options to be obtained elsewhere (from a [secondary instance](#secondary-instances)). | `<value>` | Child of `<item>` or `<itemset>` that defines a choice value. -Below is an example of a labels, an output, a hint, an itemset and value used together to define a form control: +Below is an example of a label, an output, a hint, an itemset and value used together to define a form control: {% highlight xml %} <group ref="/data/loc"> @@ -84,7 +84,7 @@ The following attributes are supported on body elements. Note that most attribut ### Appearances -The appearance of the 5 form controls can be changed with appearance attributes. Appearance values usually relate to a specific [data](#data-types) or [question](#body-elements) type. See the [XLS Form specification](http://xlsform.org) for a list of appearance attributes are available for each data type. Multiple space-separated appearance values can be added to a form control in any order. +The appearance of the 5 form controls can be changed with appearance attributes. Appearance values usually relate to a specific [data](#data-types) or [question](#body-elements) type. See the [XLS Form specification](http://xlsform.org) for a list of appearance attributes that are available for each data type. Multiple space-separated appearance values can be added to a form control in any order. An appearance attribute can also be used to indicate that an [external app](#external-applications) should be used as a form control. diff --git a/_sections/60-repeats.md b/_sections/60-repeats.md index cf4625d..ba669a3 100644 --- a/_sections/60-repeats.md +++ b/_sections/60-repeats.md @@ -45,7 +45,7 @@ A `<repeat>` cannnot have a label child element. To display a label it should be ### Creation, Removal of Repeats -The default behaviour of repeats is to let the user create or remove repeats using the the user interface. The user control for creating and removing repeats can be disabled by adding the attribute `jr:noAddRemove="true()"` to the `<repeat>` element. +The default behavior of repeats is to let the user create or remove repeats using the the user interface. The user control for creating and removing repeats can be disabled by adding the attribute `jr:noAddRemove="true()"` to the `<repeat>` element. There are 2 different ways to ensure that multiple repeats are automatically created when a form loads. diff --git a/_sections/95-future.md b/_sections/95-future.md new file mode 100644 index 0000000..72fcdaa --- /dev/null +++ b/_sections/95-future.md @@ -0,0 +1,5 @@ +--- +title: Future +--- + +See the [outstanding issues list](https://github.com/opendatakit/odk-xform-spec/issues) to get an idea of how this specification will evolve. Join the conversation!