Forms

This module contains much of the support for HTML and WML forms. It's responsible for configuring and displaying widgets correctly and it's responsible for keeping track of form values and creating form submits.

Some form handling still exists outside the forms module. DOM interfaces and relevent code is found in the dom and the logdoc module. The widgets are in the widgets module. Forms filling from wand is in the wand module. Event handling is in the doc, logdoc and widgets module. Form parsing is is in the logdoc module. Actual posting (or getting) to the target server is done by the network code.

How to access form data

To access the value in a form control, you use the FormValue class that can be gotten from HTML_Element for every element of type HE_INPUT, HE_SELECT, HE_TEXTAREA, HE_KEYGEN or HE_BUTTON (and HE_OUTPUT for WebForms2).

FormValue

For normal text data

This works for most everything but checkboxes, radio buttons and select lists. HTML_Element* elm = ...; // Must be an HE_INPUT or HE_BUTTON (or HE_OUTPUT) FormValue* val = elm->GetFormValue(); // Never null OpString text; OP_STATUS status = val->GetValueAsText(elm, text); // Check status

For check boxes and radio buttons

HTML_Element* elm = ...; // Must be an HE_INPUT with InputType INPUT_CHECKBOX or INPUT_RADIO FormValueRadioCheck* val = FormValueRadioCheck::GetAs(elm->GetFormValue()); // Never null BOOL is_checked = val->IsChecked(elm);

For check boxes and radio buttons

HTML_Element* elm = ...; // Must be an HE_INPUT with InputType INPUT_CHECKBOX or INPUT_RADIO FormValueRadioCheck* val = FormValueRadioCheck::GetAs(elm->GetFormValue()); // Never null BOOL is_checked = val->IsChecked(elm);

For check boxes and radio buttons

HTML_Element* elm = ...; // Must be a HE_SELECT FormValueList* val = FormValueList::GetAs(elm->GetFormValue()); // Never null See the api for details of what you can do to a value list.

How forms are/should be parsed

Ideally in a web page every form tag creates a form. A form may have zero or more form controls (for instance input elements or button elements). In Opera we keep a number with forms and form controls which connect form controls to the right form. This number is not used for DOM inserted forms/form controls and not for XHTML.

Nested forms

In general nested forms have been illegal and ignored, but they are possible to create anyway with XML or with DOM.

Parsing HTML

In pure HTML (not XML) nested forms are illegal and the parsing used is one compatible with old browsers. Since forms cannot be nested, the parser needs only to remember which form is the current actives. If a new form tag is seen by the parser while there already is one form active (thus illegally nested) it is ignored from a form structure perspective (the old form remains the current active form). There may still be an HE_FORM element which is accessible from DOM and used in layout but it will not contain any form controls and it will not be seen in form collections from DOM.

Whenever a </form> is encountered and a current form is active, we close the active form. That is even if that </form> from a HTML/XML structure point of view belongs to some other <form> tag than the current active one.

When we encounter a form control we set it to belong to the current active form, or to be free if there is none. Free controls have the form number -1, but as do form controls inserted by DOM.

Example:

<form id="outer-form"> <input id="control-1" /> <form id="inner-form-1"> <input id="control-2" /> </form> <form id="inner-form-2"> <input id="control-3" /> </form> </form>

Here control-1 and control-2 will belong to outer-form. inner-form-1 will not exist from a form point of view, but its end tag will close outer-form. control-3 will belong to inner-form-2. The last end-form tag is trailing and doesn't belong to any form.

Parsing XHTML

For XHTML the tree structure is everything. A form control belongs to the form that is closest parent, or is a free control if it has no such parent.

In the example above all three forms will have one control each. control-1 will belong to outer-form, control-2 will belong to inner-form-1 and control-3 will belong to inner-form-2.

DOM inserted forms and controls

For DOM inserted forms and form controls we have the same treatment as for XHTML, we look at tree structure primarily.

WebForms2

Forms has an optional part - WebForms2 - that is still under development. It consists of forms extensions as layed out in the Web Forms 2 specification.

Modules that use the forms module and modules the forms module uses

Forms is used by:

It uses:

Externally usable classes

See API Documentation for details.

Form
Form submission
FormValue and all its subclasses
To access and change form data. They also keep important meta information about form controls, such as the current active CSS psueudo classes, and knows how to calculate those.
FormObject and all its subclasses
The widget part of a form control. This only exists if the form is layed out on the web page.
FormSuggestion
Class used to provide suggestion lists for widgets
FormValidator (webforms2 only)
Checks if a form contains "valid" data.
TemplateHandler (webforms2 only)
Handles templates á la web forms 2.
WebForms2Number (webforms2 only)
Parser methods for numbers á la web forms 2.

Externally usable data types

See API Documentation for details.
MonthSpec (webforms2 only)
A month and a year
DaySpec (webforms2 only)
A day, month and a year
WeekSpec (webforms2 only)
A week and year
TimeSpec (webforms2 only)
Hour, minute and optionally second

Memory management

OOM policy

Sad to say, the module uses a mix of OOM policys, but in all new code OP_STATUS should be used. Right now LEAVE is used at some places.

In case of a OOM error the objects will clean up their internal state and propagate the error to the caller, except for Form::GetURL that returns an empty URL instead.

Heap memory usage

Operations that submit data will normally use memory proportional to the amount of data in the form controls. Other operations will use memory proportional to the number of (not hidden) form elements.

Stack memory usage

The module uses no recursive algorithms so the usage is bounded and not very large (less than 1024 bytes).

Memory ownership

The classes take care of their own memory.

Temporary buffers

Both TempBuf and TempBuf2 are used internally by GetURL().

Memory tuning

No tuning possible.

Tests and coverage

Any form page will get a quite high coverage in non webforms2 code. The selftests for webforms2 will get a high coverage in the rest of the code.

Design choices

Some of the old code has been written by many people and lacks a common design. Basically most of the code act as utility code called from other places or as proxy code between the layout module and the widgets.

The main goals are the same as for Opera in general. Correct, fast, low footprint and non-blocking.

Improvements