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.
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
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);
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);
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.
In general nested forms have been illegal and ignored, but they are possible to create anyway with XML or with DOM.
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.
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.
For DOM inserted forms and form controls we have the same treatment as for XHTML, we look at tree structure primarily.
Forms is used by:
It uses:
See API Documentation for details.
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.
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.