mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 05:09:12 +00:00
LibWeb: Implement HTMLFormElement::checkValidity (constraint validation)
This change implements the requirements from the HTML spec at https://html.spec.whatwg.org/#statically-validate-the-constraints and https://html.spec.whatwg.org/#dom-form-checkvalidity — the parts of the HTML constraint validation API (aka “client-side form validation”) https://html.spec.whatwg.org/#the-constraint-validation-api for HTMLFormElement itself — as well as the code for the requirements at https://html.spec.whatwg.org/#check-validity-steps, which are the shared requirements for the checkValidity method for individual form controls.
This commit is contained in:
parent
b4e47f198a
commit
7c34746571
Notes:
github-actions[bot]
2025-02-26 04:14:35 +00:00
Author: https://github.com/sideshowbarker
Commit: 7c34746571
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3674
Reviewed-by: https://github.com/tcl3 ✅
4 changed files with 62 additions and 2 deletions
|
@ -226,6 +226,20 @@ WebIDL::ExceptionOr<void> FormAssociatedElement::set_form_action(String const& v
|
||||||
return html_element.set_attribute(HTML::AttributeNames::formaction, value);
|
return html_element.set_attribute(HTML::AttributeNames::formaction, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#check-validity-steps
|
||||||
|
bool FormAssociatedElement::check_validity_steps()
|
||||||
|
{
|
||||||
|
// 1. If element is a candidate for constraint validation and does not satisfy its constraints
|
||||||
|
if (is_candidate_for_constraint_validation() && !satisfies_its_constraints()) {
|
||||||
|
auto& element = form_associated_element_to_html_element();
|
||||||
|
// 1. Fire an event named invalid at element, with the cancelable attribute initialized to true
|
||||||
|
element.dispatch_event(DOM::Event::create(element.realm(), EventNames::invalid, { .cancelable = true }));
|
||||||
|
// 2. Return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#candidate-for-constraint-validation
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#candidate-for-constraint-validation
|
||||||
bool FormAssociatedElement::is_candidate_for_constraint_validation() const
|
bool FormAssociatedElement::is_candidate_for_constraint_validation() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,9 @@ public:
|
||||||
// https://html.spec.whatwg.org/multipage/forms.html#concept-submit-button
|
// https://html.spec.whatwg.org/multipage/forms.html#concept-submit-button
|
||||||
virtual bool is_submit_button() const { return false; }
|
virtual bool is_submit_button() const { return false; }
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#check-validity-steps
|
||||||
|
bool check_validity_steps();
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#candidate-for-constraint-validation
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#candidate-for-constraint-validation
|
||||||
bool is_candidate_for_constraint_validation() const;
|
bool is_candidate_for_constraint_validation() const;
|
||||||
|
|
||||||
|
|
|
@ -561,11 +561,48 @@ unsigned HTMLFormElement::length() const
|
||||||
return elements()->length();
|
return elements()->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#statically-validate-the-constraints
|
||||||
|
HTMLFormElement::StaticValidationResult HTMLFormElement::statically_validate_constraints()
|
||||||
|
{
|
||||||
|
// 1. Let controls be a list of all the submittable elements whose form owner is form, in tree order.
|
||||||
|
auto controls = get_submittable_elements();
|
||||||
|
// 2. Let invalid controls be an initially empty list of elements.
|
||||||
|
GC::RootVector<GC::Ref<DOM::Element>> invalid_controls(realm().heap());
|
||||||
|
// 3. For each element field in controls, in tree order:
|
||||||
|
for (auto& element : controls) {
|
||||||
|
auto& field = as<FormAssociatedElement>(*element);
|
||||||
|
// 1. If field is not a candidate for constraint validation, then move on to the next element.
|
||||||
|
if (!field.is_candidate_for_constraint_validation())
|
||||||
|
continue;
|
||||||
|
// 2. Otherwise, if field satisfies its constraints, then move on to the next element.
|
||||||
|
if (field.satisfies_its_constraints())
|
||||||
|
continue;
|
||||||
|
// 3. Otherwise, add field to invalid controls.
|
||||||
|
invalid_controls.append(field.form_associated_element_to_html_element());
|
||||||
|
}
|
||||||
|
// 4. If invalid controls is empty, then return a positive result.
|
||||||
|
if (invalid_controls.is_empty())
|
||||||
|
return { true, invalid_controls };
|
||||||
|
// 5. Let unhandled invalid controls be an initially empty list of elements.
|
||||||
|
GC::RootVector<GC::Ref<DOM::Element>> unhandled_invalid_controls(realm().heap());
|
||||||
|
// 6. For each element field in invalid controls, if any, in tree order:
|
||||||
|
for (auto& field : invalid_controls) {
|
||||||
|
// 1. Let notCanceled be the result of firing an event named invalid at field, with the cancelable attribute
|
||||||
|
// initialized to true.
|
||||||
|
auto not_canceled = field->dispatch_event(DOM::Event::create(this->realm(),
|
||||||
|
EventNames::invalid, { .cancelable = true }));
|
||||||
|
// 2. If notCanceled is true, then add field to unhandled invalid controls.
|
||||||
|
if (not_canceled)
|
||||||
|
unhandled_invalid_controls.append(field);
|
||||||
|
}
|
||||||
|
// 7. Return a negative result with the list of elements in the unhandled invalid controls list.
|
||||||
|
return { false, unhandled_invalid_controls };
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-checkvalidity
|
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-checkvalidity
|
||||||
WebIDL::ExceptionOr<bool> HTMLFormElement::check_validity()
|
WebIDL::ExceptionOr<bool> HTMLFormElement::check_validity()
|
||||||
{
|
{
|
||||||
dbgln("(STUBBED) HTMLFormElement::check_validity(). Called on: {}", debug_description());
|
return statically_validate_constraints().result;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-reportvalidity
|
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-reportvalidity
|
||||||
|
|
|
@ -78,6 +78,12 @@ public:
|
||||||
GC::Ref<HTMLFormControlsCollection> elements() const;
|
GC::Ref<HTMLFormControlsCollection> elements() const;
|
||||||
unsigned length() const;
|
unsigned length() const;
|
||||||
|
|
||||||
|
struct StaticValidationResult {
|
||||||
|
bool result;
|
||||||
|
GC::RootVector<GC::Ref<DOM::Element>> unhandled_invalid_controls;
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticValidationResult statically_validate_constraints();
|
||||||
WebIDL::ExceptionOr<bool> check_validity();
|
WebIDL::ExceptionOr<bool> check_validity();
|
||||||
WebIDL::ExceptionOr<bool> report_validity();
|
WebIDL::ExceptionOr<bool> report_validity();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue