Online Form HTML Specification


Conventions Used in This Document

Supported versions of HTML are 4+ and XHTML 1.  HTML 3 doesn't support id and class attributes, which are required.

Syntax of elements follows CSS Selector style (also used by jQuery) not XPath style.

References to <input> also apply to <button>, <select>, and <textarea> unless otherwise stated.

References to <button> also apply to <input type="submit"> and <input type="button">.  In the context of selectors this means "button" also applies to "input[type='submit']" and "input[type='button']"

Required Elements

Container: #form-container

A container to wrap everything.  In the future the app may want to remove all children in this container and present it's own HTML to preserve your look and feel when gathering additional data from or presenting messages to the user (e.g., when asking why a form is being rejected or confirming certain actions).

Messages: #form-container #form-messages

A container where the app will insert error messages.  The message HTML uses Bootstrap 2.3.2 messages and therefore assumes a compatible version of Bootstrap and its accompanying JavaScript (which in turn requires jQuery).  All these dependencies are available for you to link to in Static Assets for Use In Forms.  

You may also choose not to include any of these dependencies and instead style the HTML yourself.  The HTML for these messages will be structures like this:

<div class="alert alert-error"> <div> <strong>$ERROR_1: </strong>$MESSAGE_1 </div> <div> <strong>$ERROR_2: </strong>$MESSAGE_2 </div> <!-- ... --> </div>

Form Sections: #form-container form.form-section

Individual sections of the form.  More technically speaking, individual <form> elements in the HTML document.

Button Controls: #form-container form.form-section .controls

This node will be hidden when future lifecycle stages are viewing the form.

Approve Button: #form-container form.form-section .controls button[value="approve"]

This might be labeled as "Submit" on the initial form, or whatever else you'd like.

Section Visibility: .visiblefromall, .visiblefrom-SECTION_ID

Technically these classes are optional but by not specifying visibility a section will only be visible to itself. I.e., future approving sections will not be able to see previous sections. It is recommended to use the "visiblefromall" class on all form elements unless you specifically want to hide a section.

Form sections with the “visiblefromall” class will be visible to all other form sections stages in the lifecycle.  Sections restricted to one or multiple “visiblefrom-SECTION_ID” will only be visible to the form sections with an ID attribute matching the SECTION_ID. Sections with no visibility rules will not be visible to other sections.

These classes can be applied to any HTML element.  The only difference is that form sections default to be hidden to other sections while all other HTML node default to being visible if their parent form section is visible.

Optional Elements

Reject Button: #form-container form.form-section .controls button[value="reject"]

This might be labeled as "Cancel" or "Delete" on the initial form.

Save Button: #form-container form.form-section .controls button[value="save"]

This should probably be the default action if no value is set.

Return Button: #form-container form.form-section .controls button[value="return"]

Allows user to return the form to a previous section.  This button is always available in the user's form queue.

Required Fields: input.required

Makes that field required for "approve" action.  If that field is missing on error message reading "Missing required field: FIELD_NAME is required" will be added to the messages container with underscores in the FIELD_NAME string being converted to spaces.

Best Practices

Avoid Spaces in Field Names

When field names are presented to the user (e.g., for a missing required field) underscores will be converted to spaces.

Disabled Field with Corresponding Hidden Field

Browsers don't submit data for disabled fields.  To have the data saved, include a matching hidden field with the value.

<input type="text" name="myfield" value="Uneditable" disabled> <input type="hidden" name="myfield" value="Uneditable">

Submitting a hidden value is still vulnerable to HTML modification/parameter injection.  To avoid this don't put the content in a field at all but instead style another HTML element to look like a disabled field.  The stylesheet provided by online forms includes a class to style a div like a disabled form field.

<link rel="stylesheet" href="https://static.forms.northwestern.edu/1/css/northwestern-forms.css"> <div class="form-pseudofield form-print-input-text">Uneditable</div>

Checkboxes Always Have Unique Names

This should only be true within a given <form> however the engine will not allow duplicate names even in different <form> elements. This is considered a bug (issue #121) and slated to be fixed in the Spring 2015 release.

Each checkbox must have it's own unique name or only the value of the last checkbox will be saved and all other values with identical names will be discarded.

Name of Multiselect Ends with []

Multiselect fields must end with [] in the name attribute:

Don't Use Square Brackets in Field Names (except multiselects)

The form engine doesn't properly handle square brackets in field names, except at the end of multiselect fields, which causes data to be lost.  This is considered a bug (issue #140) but there is no immediate intention to fix it since there haven't been any production cases of square brackets being necessary.

HTML Transformations

Disabled Form Sections

When a form section is disabled the parent form will receive a "disabled" class and each form element will receive the disabled attribute. The node containing your buttons (tagged with the "controls" class) will also be removed from the document.

Removing Classes Specifying Visibility Rules, Email Alerts, and Optional Sections

When a form is rendered to an end user, all class and custom attributes to specify visibility rules, email alerts, and optional section will be stripped.  Form authors are therefore discouraged from using these classes as CSS rules.  The specific list of classes stripped are:

form.visiblefromall (when the form is also .form-section)
form.visiblefrom-* (when the form is also .form-section)
#form-container .visiblefrom-*
form.formcycle-optional-onlyif-* (when the form is also .form-section)
formcycle-from-email-address and formcycle-from-email-name attributes on form.form-section

When a form's print view is rendered text inputs, selects, and text areas will be converted to div tags with the value of the original node as the inner HTML of the div.  Each div will have special classes applied to allow designers to style the new divs as form elements, though the provided stylesheet will handle this automatically.  No other attributes or styles will be carried over.

The original nodes will remain in the document (e.g., so JavaScript can continue to interact with them) with a style "display:none;" applied.

The rationale for this conversion is that div node can accept more style settings, particularly related to preventing text from overflowing the node and being truncated.

Form Field

Classes applied after conversion

Form Field

Classes applied after conversion

Submit buttons, radio buttons, checkboxes

No conversion

Text inputs

form-print-input-text

Special text inputs (e.g., email, date)

form-print-input-TYPE (e.g., form-print-input-email, form-print-input-date)

textarea

form-print-textarea

select

form-print-select

select multiple

Parent div: form-print-select-multiple
Each child div: form-print-select-multiple-option