- From: Dave Raggett <dsr@w3.org>
- Date: Wed, 25 Oct 2006 10:26:42 +0100 (BST)
- To: John Boyer <boyerj@ca.ibm.com>
- Cc: www-forms@w3.org, www-forms-request@w3.org
I think most web developers would be a little confused over the use of "/" in the sum. The appearance of line total is fine, but it shouldn't be required. Consider the following from my testbed: <form name="form1"> <fieldset name="lineItem" repeat-number="4"> <legend>Repeating groups of fields</legend> <label for="item">Product Name</label> <label for="quantity">Number Purchased</label> <label for="unitprice">Price Per Unit</label> <select name="item"> <option></option> <option value="hammer">Hammer</option> <option value="screwdriver">Screwdriver</option> <option value="spanner">Spanner</option> <option value="saw">Saw</option> <option value="drill">Electric Drill</option> </select> <input name="quantity" datatype="number" title="number purchased"/> <input name="unitprice" datatype="number" title="price per unit" calculate="price(item)" readonly="readonly"/> </fieldset> <p><label for="total">Total price</label> <input name="total" readonly="readonly" calculate="sumover(lineItem, quantity*unitprice)"/> <button type="submit">Submit</button> <button type="reset">Reset</button></p> </form> It would be inappropriate to include "javascript:" as a prefix for the expressions since they need to be rewritten before passing to the JavaScript eval function in order to be able to access the browser's built in support for the HTML Forms object model. This ability to rewrite expressions can also be used when it comes to exporting the form as an XForms model. I think summing quantity times unit price over the rows in the fieldset line item is an easier to understand way of stating the intention for the total than sum(lineItem/lineTotal) which most people will think is some kind of division. This is where I think it is very important to invite respected web developers to provide the perspective of the developer community. This will go a long way to ensuring that whatever we do isn't rejected by that community. I have used read only input elements rather than output elements to ensure that they are part of the HTML forms model as supported by existing browsers. It is possible to use scripts to support an output element, but it is very messy to do in a cross browser way and I can provide the gory details upon demand. The title attribute provides a tooltip for the fields and appears when the mouse pointer hovers over a field. To prefill the order form, one option is to simply include the corresponding input and select elements for each of the fields in all of the rows. Another is to provide a URI e.g. as an attribute on the form element, and to use XmlHttpRequest to fetch the data from the server. I aim to provide working demonstrations of both by next Tuesday. Dave Raggett <dsr@w3.org> http://www.w3.org/People/Raggett On Tue, 24 Oct 2006, John Boyer wrote: > The following is by no means finalized, but is rather a continuation of > the discussion the working group has been having. > > That being said, it would be nice if the following markup implied the > XForms data model and UI below it: > > <form name="form1" action="example.org"> > <fieldset name="lineItem" repeat-number="2"> > <legend>ACME Purchase Order</legend> > > <label for="item">Product Name</label> > <label for="quantity">Number Purchased</label> > <label for="unitprice">Price Per Unit</label> > <label for="lineTotal">Line Total</label> > > <select name="item"> > <option></option> > <option value="hammer">Hammer</option> > <option value="screwdriver">Screwdriver</option> > <option value="spanner">Spanner</option> > </select> > > <input name="quantity" datatype="number" title="number purchased"/> > > <input name="unitprice" datatype="number" title="price per unit" > calculate="javascript:price(item)"/> > > <input name="lineTotal" datatype="number" title="line total" > calculate="quantity * price"/> > </fieldset> > > <p> > <label for="total">Total price</label> > <input name="total" calculate="sum(lineItem/lineTotal)"/> > > <button type="submit">Submit</button> > <button type="reset">Reset</button> > </p> > </form> > > The above should correspond to something like the following: > > > <group id="form1_group" model="form1_model"> > > <model id="form1_model"> > <submission id="form1_submission" action="http://example.org" > method="urlencoded-post" ... /> > > <instance id="form1_instance"> > <data xmlns=""> > <lineItem> > <item></item> > <quantity></quantity> > <unitprice></unitprice> > <lineTotal></lineTotal> > </lineItem> > <lineItem> > <item></item> > <quantity></quantity> > <unitprice></unitprice> > <lineTotal></lineTotal> > </lineItem> > <total></total> > </data> > </instance> > > <bind nodeset="lineItem"> > <bind nodeset="quantity" mipcontext=".." type="xsd:double"/> > <bind nodeset="unitprice" mipcontext=".." > calculate="javascript:price(item)" type="xsd:double"/> > <bind nodeset="lineTotal" mipcontext=".." calculate="unitprice * > quantity" type="xsd:double"/> > </bind> > <bind nodeset="total" mipcontext=".." > calculate="sum(lineItem/lineTotal)"/> > </model> > > <table> > <caption>ACME Purchase Order</caption> > <thead> > <tr><th>Product Name</th><th>Number Purchased</th><th>Price Per > Unit</th><th>Line Total</th></tr> > </thead> > <!-- Could use repeat attrs like this: <tbody > repeat-nodeset="lineItem" repeat-number="2"> --> > <tbody> > <repeat nodeset="lineItem" number="2"> > <tr> > <td> > <select1 name="item"> > <label>Product Name</label> > <item> <label/> <value/> </item> > <item> <label>Hammer</label> <value>hammer</value> > </item> > <item> <label>Screwdriver</label> > <value>screwdriver</value> </item> > <item> <label>Spanner</label> <value>spanner</value> > </item> > </select1> > </td> > <td> > <input ref="quantity"> > <label>Number Purchased</label> > <hint>number purchased</hint> > </input> > </td> > <td> > <input ref="unitprice"> > <label>Price Per Unit</label> > <hint>price per unit</hint> > </input> > </td> > <td> > <input ref="lineTotal"> > <label>Line Total</label> > <hint>line total</hint> > </input> > </td> > </tr> > </repeat> > </tbody> > > <p> > <input ref="total"> > <label>Total price</label> > </input> > > <submit submission="form1_submission"> > <label>Submit</label> > </submit> > > <trigger> > <label>Reset</label> > <reset ev:event="DOMActivate" model="form1_model"/> > </trigger> > </p> > </group> > > Of course there are details to be quibbled over, but this gives a kind of > first-brush Rosetta stone. > > Cheers, > John M. Boyer, Ph.D. > STSM: Workplace Forms Architect and Researcher > Co-Chair, W3C Forms Working Group > Workplace, Portal and Collaboration Software > IBM Victoria Software Lab > E-Mail: boyerj@ca.ibm.com http://www.ibm.com/software/ > > Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer > > > > > > Dave Raggett <dsr@w3.org> > Sent by: www-forms-request@w3.org > 10/24/2006 05:05 AM > > To > www-forms@w3.org > cc > > Subject > forms-lite and data models > > > > > > > > A key goal for the forms-lite testbed [1] was to work on a wide > variety of current web browsers. The next decision was whether to > make use of the built-in submission mechanism or to come up with > something else based upon XmlHttpRequest (Ajax). I found a couple of > disadvantages for using Ajax. The first is that it is hard to fully > emulate the conventional semantics for submit, where the current > page is pushed onto the browser history and replaced by a new page > sent by the server. The second is that you couldn't support file > upload as part of the form's data. The Web API working group has > recently published a new working draft for uploading files from web > page scripts, but I don't believe it is widely supported as yet. I > therefore decided to focus initially on using the built in support > for form submission. > > The HTML forms data model can be described as a set of named forms > where each form has a collection of named fields. The HTML DOM is > (mostly) defined in the W3C DOM2 Recommendation [2] > > document.forms[0] is the first form > > You can access the field by its name, e.g. > > document.forms[0].x for the field named x > > Fields have properties, e.g. name, type, value, checked, readonly, > and disabled. > > If there is more than one instance of a field with the same name > then the "form.name" evaluates to an array of the instances. This > is particularly pertinent to radio buttons (type is "radio"), but > also applies to other types and this can be taken advantage of when > you want to make use of repeating sets of fields. > > The value of a field is generally given by its value attribute > with exceptions for radio buttons and checkboxes. For checkboxes > the checked property is a boolean that indicates whether or not > the checkbox is ticked. The field's value is only included in the > submitted data if checked is true. For radio buttons, you need > to iterate through the array of fields with the same name to find > which one has checked equal to true. The value for this field is > then included with the submitted data. If the disabled property > is true then the field's value won't be included in the submitted > data -- this overrides the checked property. > > When it comes to expressions provided by attribute values set on > particular fields, then the form associated with the field provides > a scope for resolving references to other fields. Forms-lite > lets you write the following: > > <input name="x" type="number"/> > <input name="y" type="number"/> > <input name="z" type="number" calculate="x+y"/> > > where x, y and z are all part of the same form. The type of the > field is important to how the expression is evaluated. In > particular, ECMAScript defines the + operator to behave differently > according to the types of its arguments. On strings it acts as a > concatenator, whilst on numbers it adds them. > > ECMAScript also supports the notion of nested scopes. Thus locally > defined variables take precedent over globally defined variables. > Forms-lite takes advantage of this to allow you to refer to > global variables and functions from within expressions. Names of > fields for the current form take precedence over global variables. > > Forms-lite allows you to define a repeating set of fields. This > is analogous to a set of rows in a spreadsheet, where the field > name identifies the column, and a row index identifies the row. > > For expressions defined on fields within repeating set of fields, > the scope is the current row, then the set of non repeating > fields for the current form, and then the global scope. The > expressions never include a row index. Thus in the above example, > all three fields could be part of a repeating fieldset, and > correspond to a set of rows, where in each row the value of > z is the sum of x and y. > > Forms-lite also allows you to write expressions that are > evaluated over a set of rows. So far I have implemented > two such second order functions: > > count(name) > Where name identifies a checkbox in a repeating set > of fields. This function counts the number of ticked > checkboxes in the column. > > sumover(name, expr) > Where name identifies a repeating set of fields. This > function sums the result of evaluating the expression > expr over each row in the repeating set of fields. > > Forms-lite provides a mechanism for defining repeating sets of > fields using the HTML fieldset element as a container for the > set of fields to be repeated. The fieldset element defines a > scope, although this isn't reflected in the HTML DOM directly. > The count function described above should perhaps take the > name of a fieldset and use that to restrict its scope to just > the checkboxes contained by that fieldset. > > Repeating sets of fields and radio buttons don't mix well in the > HTML DOM. This is because the group of radio buttons is represented > in the DOM as an array of fields. This makes it impractical to > include radio buttons in a repeated fieldset element. The work > around is to use an HTML select element instead. > > Another issue with repeated fieldsets that are generated dynamically > relates with how web browsers support the "back" and "reload" > operations. When you move away from a page, the browser saves the > current state of the form as part of the history. When you go back > to that page, the browser restores that state based upon the page's > markup. If a repeating set of fields is generated dynamically as a > result of the page's onload event, only the values for the first row > will be restored. Forms-lite deals with this problem by clearing the > state of such repeating fieldsets. > > Ideally, the DOM would provide a means for the script to access the > state recorded in the history as that would then allow the state of > all rows to be restored. This is something that the Web API working > group could perhaps be asked to provide as an extension to the DOM > for the browser history. > > Some weird things I discovered: > > - On IE you need to use the htmlFor property when you want the > the value of the for attribute on the label element > > - On IE you need to use the className property when you want > to get or set the value of the class attribute. Luckily > most other browsers also support className for this purpose > > - On Opera, you can't access the legend element within a fieldset > element by traversing the DOM tree. You can however access it > via calling getElementsByTagName("legend") on the fieldset. > > - Some browsers will fall back to the name attribute if the id > attribute is mising on the input element when it comes to > binding a label via its for attribute > > - Some browsers will include the fieldset element as part of > the form when you provide a name attribute on the fieldset. > > - Opera coerces the value of the type attribute returned with > getAttribute to "text" if Opera doesn't recognize the type. > > There needs to be a well defined interoperable way to identify > whether a browser has a native implementation so that you can > take advantage of that rather than relying on interpreting the > attributes via a script library. > > Native implementations may have weaknesses, so that you may still > want to use a script library to define the behavior, to ensure that > end-users get the same behavior on all browsers. It would be > desirable to have a well defined way to disable the native > implementation in such cases. > > In HTML, the form element encloses the fields that belong to it. > This is occasionally inconvenient, and it would be desirable to > be able to instead use an attribute to reference the form by > name. I have yet to experiment with this and to determine whether > this can be made to work on existing browsers. It would involve > inserting the fields into the form's object model via a script, > but whether the submit mechanism would work in that case needs > experimental verification. > > [1] http://people.w3.org/~dsr/forms-lite/ > [2] http://www.w3.org/TR/DOM-Level-2-HTML > > > Dave Raggett <dsr@w3.org> http://www.w3.org/People/Raggett > > >
Received on Wednesday, 25 October 2006 09:26:54 UTC