paulb@151 | 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
paulb@151 | 2 | <html xmlns="http://www.w3.org/1999/xhtml"> |
paulb@151 | 3 | <head> |
paulb@151 | 4 | <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type" /> |
paulb@151 | 5 | <title>Creating Applications: Adding Multivalued Fields</title> |
paulb@151 | 6 | <meta name="generator" |
paulb@151 | 7 | content="amaya 8.1a, see http://www.w3.org/Amaya/" /> |
paulb@151 | 8 | <link href="styles.css" rel="stylesheet" type="text/css" /> |
paulb@151 | 9 | </head> |
paulb@151 | 10 | <body> |
paulb@151 | 11 | <h1>Creating Applications: Adding Multivalued Fields</h1> |
paulb@151 | 12 | <p>Although some applications only require multiple-choice fields where |
paulb@151 | 13 | only a single value may be chosen, in many situations it is desirable |
paulb@151 | 14 | to be able to choose an arbitrary number of values for a particular |
paulb@151 | 15 | field. However, up to this point, we have been content to |
paulb@151 | 16 | represent form data using a single attribute on a single element to |
paulb@151 | 17 | represent any given field value. With multivalued fields, we must |
paulb@151 | 18 | choose a different strategy in using XML to represent such information.</p> |
paulb@151 | 19 | <p>Let us consider permitting multiple type values to be associated |
paulb@151 | 20 | with our items. We revise our <a href="data.html">form data structure</a> |
paulb@151 | 21 | to |
paulb@151 | 22 | be the following:</p> |
paulb@157 | 23 | <pre><?xml version="1.0"?><br /><structure><br /> <item value="some value"><br /> <type><br /> <type-enum value="some type"/><br /> <type-enum value="some other type"/><br /> </type><br /> <subitem subvalue="some other value"/><br /> </item><br /></structure></pre> |
paulb@151 | 24 | <h2>Multivalued Fields</h2> |
paulb@151 | 25 | <p>We shall now take advantage of those HTML form fields which permit |
paulb@151 | 26 | users to select one |
paulb@151 | 27 | or many values presented in a list or menu.</p> |
paulb@151 | 28 | <form method="post" action="" name="single"> |
paulb@151 | 29 | <p>Some item: <input name="value" value="some value" /><input |
paulb@151 | 30 | name="remove" value="Remove" type="submit" /></p> |
paulb@151 | 31 | <p>Item type: |
paulb@151 | 32 | <select multiple="multiple" name="type"> |
paulb@151 | 33 | <option>(Not selected)</option> |
paulb@151 | 34 | <option>Important</option> |
paulb@151 | 35 | <option>Not important</option> |
paulb@151 | 36 | <option>Personal</option> |
paulb@151 | 37 | </select> |
paulb@151 | 38 | </p> |
paulb@151 | 39 | <p>Itself containing more items:</p> |
paulb@151 | 40 | <p>Sub-item: <input name="subvalue" value="some other value" /><input |
paulb@151 | 41 | name="remove2" value="Remove" type="submit" /></p> |
paulb@151 | 42 | </form> |
paulb@151 | 43 | From the item type list many value may now be selected. |
paulb@151 | 44 | <p>Taking the example HTML code from before, we can add a |
paulb@151 | 45 | definition of this new list to the template to produce something |
paulb@151 | 46 | like this:</p> |
paulb@151 | 47 | <pre><html xmlns="http://www.w3.org/1999/xhtml"<br /> xmlns:template="http://www.boddie.org.uk/ns/xmltools/template"><br /><head><br /> <title>Example</title><br /></head><br /><body template:element="structure"><br /><form action="" method="POST"><br /><br /><!-- Template text between the start and the interesting part. --><br /><br /><div template:element="item"><br /> <p><br /> Some item: <input template:attribute="value" name="{template:this-attribute()}" type="text" value="{$this-value}" /><br /> <input name="remove={template:this-element()}" type="submit" value="Remove" /><br /> </p><br /> <span |
paulb@157 | 48 | style="font-weight: bold;"><p></span><br /> Item type:<br /> <select template:element="type" name="<span |
paulb@157 | 49 | style="font-weight: bold;">{template:list-attribute('type-enum', 'value')}</span>" <span |
paulb@151 | 50 | style="font-weight: bold;">multiple="multiple"</span>><br /> <option template:element="type-enum" template:expr="<span |
paulb@151 | 51 | style="font-weight: bold;">@value-is-set</span>" template:expr-attr="selected"<br /> template:value="@value" value="{@value}" /><br /> </select><br /> </p><br /> <p><br /> Itself containing more items:<br /> </p><br /> <p template:element="subitem"><br /> Sub-item: <input template:attribute="subvalue" name="{template:this-attribute()}" type="text" value="{$this-value}" /><br /> <input name="remove2={template:this-element()}" type="submit" value="Remove" /><br /> </p><br /> <p><br /> <input name="add2={template:this-element()}" type="submit" value="Add subitem" /><br /> </p><br /></div><br /><p><br /> <input name="add={template:this-element()}" type="submit" value="Add item" /><br /></p><span |
paulb@151 | 52 | style="font-weight: bold;"><br /><br /></span><!-- Template text between the interesting part and the end. --><br /><br /></form><br /></body><br /></html></pre> |
paulb@151 | 53 | <p>From the previous <a href="mulitple.html">single-valued case</a>, |
paulb@151 | 54 | some crucial changes have been made:</p> |
paulb@151 | 55 | <ol> |
paulb@151 | 56 | <li>The <code>select</code> element remains mapped onto the <code>type</code> |
paulb@151 | 57 | element in the form data structure. However, we indicate in the name of |
paulb@151 | 58 | the <code>select</code> |
paulb@151 | 59 | element that the value submitted maps onto a special kind of attribute. |
paulb@151 | 60 | Instead of mapping onto a single attribute on a single element, the |
paulb@151 | 61 | value maps onto a single attribute on a single element <span |
paulb@151 | 62 | style="font-style: italic;">for each value submitted</span>. So for |
paulb@157 | 63 | each value selected in the list or menu, a <code>type-enum</code> |
paulb@157 | 64 | element is created (inside the <code>type</code> element) with a <code>value</code> |
paulb@151 | 65 | attribute containing that value.</li> |
paulb@151 | 66 | <li>Of course, the <code>select</code> element now has a <code>multiple</code> |
paulb@151 | 67 | attribute defined to permit multiple value selections.</li> |
paulb@151 | 68 | <li>Inside the <code>select</code> element, the <code>option</code> |
paulb@151 | 69 | element mapping onto |
paulb@151 | 70 | a <code>type-enum</code> element using a different <code>template:expr</code> |
paulb@151 | 71 | condition than was used before.</li> |
paulb@151 | 72 | </ol> |
paulb@151 | 73 | <h2>Output Structures</h2> |
paulb@157 | 74 | <p>Unlike in the single-valued case, the revised the form data |
paulb@157 | 75 | structure for input is almost the same as the structure used by the |
paulb@157 | 76 | template. Indeed, the subtle differences cannot be represented in our |
paulb@157 | 77 | simplistic presentation of the structure:</p> |
paulb@157 | 78 | <pre><?xml version="1.0"?><br /><structure><br /> <item value="some value"><br /> <type><br /> <type-enum value="some type"/><br /> <type-enum value="some other type"/><br /> </type><br /> <subitem subvalue="some other value"/><br /> </item><br /></structure></pre> |
paulb@157 | 79 | <p>In fact, the principal difference arises through the number of <code>type-enum</code> |
paulb@157 | 80 | elements that occur in the input, representing the values selected by |
paulb@157 | 81 | the user, and the number that occur in the output, representing the |
paulb@157 | 82 | complete range of values available for selection. |
paulb@151 | 83 | </p> |
paulb@151 | 84 | <h3>Presenting the Extra Values</h3> |
paulb@151 | 85 | <p>In most respects, the presentation of the extra values is the same |
paulb@151 | 86 | as in the single-valued case. The result of the presentation of the |
paulb@157 | 87 | extra values is that the <code>type</code> element in the |
paulb@151 | 88 | this example structure fragment...</p> |
paulb@157 | 89 | <pre><type><br /> <type-enum value="1"/><br /> <type-enum value="2" value-is-set="true"/><br /> <type-enum value="3" value-is-set="true"/><br /></type><br /></pre> |
paulb@151 | 90 | <p>...is transformed into something resembling this HTML code:</p> |
paulb@157 | 91 | <pre><select name="..." multiple="multiple"><br /> <option value="1">1</option><br /> <option value="2" selected="selected">2</option><br /> <option value="3" selected="selected">3</option><br /></select><br /></pre> |
paulb@157 | 92 | <p>One principal issue arises when considering the above |
paulb@157 | 93 | transformation: where does the special <code>value-is-set</code> |
paulb@157 | 94 | attribute |
paulb@157 | 95 | come from?</p> |
paulb@151 | 96 | <ul> |
paulb@151 | 97 | </ul> |
paulb@157 | 98 | Here, we have to do two things: to include the full range of possible |
paulb@157 | 99 | values so that the user may select from that range, and yet we must |
paulb@157 | 100 | remember which values were previously selected. If we just merged |
paulb@157 | 101 | the <code>type-enum</code> elements into the <code>type</code> |
paulb@157 | 102 | element, we would lose track of which values were selected. Therefore, |
paulb@157 | 103 | we need to employ a different strategy in remembering those values than |
paulb@157 | 104 | that of assuming that those <code>type-enum</code> elements which |
paulb@157 | 105 | are present are those which are selected. |
paulb@151 | 106 | <h2>Merging and Collecting Values</h2> |
paulb@151 | 107 | <p>As in the single-valued case, we need to insert the permitted values |
paulb@151 | 108 | into the form data so that the template may visit the <code>type-enum</code> |
paulb@151 | 109 | elements and extract those values. However, we have now introduced |
paulb@157 | 110 | another task to this activity: to mark the selected values in the |
paulb@157 | 111 | entire list of <code>type-enum</code> elements in order to |
paulb@157 | 112 | distinguish them from the values which are not selected. In other |
paulb@157 | 113 | words, we want to turn |
paulb@151 | 114 | something like this...</p> |
paulb@157 | 115 | <pre><type><br /> <type-enum value="2"/><br /> <type-enum value="3"/><br /></type><br /></pre> |
paulb@151 | 116 | <p>...into something like this:</p> |
paulb@157 | 117 | <pre><type><br /> <type-enum value="1"/><br /> <type-enum value="2" value-is-set="true"/><br /> <type-enum value="3" value-is-set="true"/><br /></type><br /></pre> |
paulb@151 | 118 | Using the same document containing all the permitted values as our |
paulb@151 | 119 | source of information to be merged into the form data, we can now |
paulb@151 | 120 | develop a stylesheet which performs the above transformation; this |
paulb@151 | 121 | stylesheet needs to work on the |
paulb@151 | 122 | following principles: |
paulb@151 | 123 | <ol> |
paulb@151 | 124 | <li>Descend into the form data structure, copying all elements, |
paulb@151 | 125 | attributes and text that the stylesheet is not programmed to recognise.</li> |
paulb@151 | 126 | <li>When encountering an <code>item</code> element (which the |
paulb@151 | 127 | stylesheet is programmed to recognise), do the following:<br /> |
paulb@151 | 128 | <ol> |
paulb@151 | 129 | <li>Copy the element "skeleton" and its attributes so that |
paulb@151 | 130 | the <code>value</code> attribute is retained.</li> |
paulb@157 | 131 | <li>Produce a new <code>type</code> element and process it.</li> |
paulb@151 | 132 | </ol> |
paulb@151 | 133 | </li> |
paulb@157 | 134 | <li>When processing a new <code>type</code> element, do the |
paulb@151 | 135 | following:<br /> |
paulb@151 | 136 | <ol> |
paulb@151 | 137 | <li>Inside this new <code>type</code> element, add the <code>type-enum</code> |
paulb@151 | 138 | elements from the |
paulb@157 | 139 | values document, and if any <code>type-enum</code> |
paulb@157 | 140 | elements were found within an existing <code>type</code> element from |
paulb@157 | 141 | the form data, specify |
paulb@151 | 142 | these for the activity.</li> |
paulb@151 | 143 | </ol> |
paulb@151 | 144 | </li> |
paulb@151 | 145 | <li>When adding the <code>type-enum</code> elements, if any of |
paulb@151 | 146 | them have a <code>value</code> attribute which matches any of the <code>value</code> |
paulb@157 | 147 | attributes of the found <code>type-enum</code> elements, set the |
paulb@157 | 148 | special <code>value-is-set</code> attribute on that <code>type-enum</code> |
paulb@151 | 149 | element.</li> |
paulb@151 | 150 | </ol> |
paulb@151 | 151 | <p>The stylesheet source code can be found in <code>examples/Common/VerySimple/Resources/structure_multivalue_types.xsl</code>, |
paulb@151 | 152 | whereas the document defined above which contains the values can be |
paulb@151 | 153 | found in <code>examples/Common/VerySimple/Resources/structure_types.xml</code>.</p> |
paulb@151 | 154 | <h3>Updating the Web Resource</h3> |
paulb@151 | 155 | <p>To update the special WebStack resource, we |
paulb@151 | 156 | now need to modify a few of the class attributes and to add a few |
paulb@151 | 157 | others:</p> |
paulb@151 | 158 | <pre> template_resources = {<br /> "structure" : ("structure_multivalue_template.xhtml", "structure_output.xsl")<br /> }<br /> transform_resources = {<br /> "types" : ["structure_multivalue_types.xsl"]<br /> }<br /></pre> |
paulb@151 | 159 | <p>With these adjustments, it should now be possible to manipulate the |
paulb@157 | 160 | items and subitems whilst specifying multiple type values on each item. |
paulb@157 | 161 | Note that it may be necessary to remove the old stylesheet for |
paulb@157 | 162 | producing output, <code>structure_output.xsl</code>, so that the |
paulb@157 | 163 | multivalue version of the template is taken into use.</p> |
paulb@167 | 164 | <h2>Further Reading</h2> |
paulb@167 | 165 | <p>Now that we have designed and implemented a simple application, it |
paulb@167 | 166 | may be worth reading some <a href="advice.html">recommendations</a> |
paulb@167 | 167 | about developing your own applications.</p> |
paulb@151 | 168 | </body> |
paulb@151 | 169 | </html> |