mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-23 04:55:15 +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: https://github.com/LadybirdBrowser/ladybird/commit/7c34746571e 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
bool FormAssociatedElement::is_candidate_for_constraint_validation() const
|
||||
{
|
||||
|
|
|
@ -91,6 +91,9 @@ public:
|
|||
// https://html.spec.whatwg.org/multipage/forms.html#concept-submit-button
|
||||
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
|
||||
bool is_candidate_for_constraint_validation() const;
|
||||
|
||||
|
|
|
@ -561,11 +561,48 @@ unsigned HTMLFormElement::length() const
|
|||
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
|
||||
WebIDL::ExceptionOr<bool> HTMLFormElement::check_validity()
|
||||
{
|
||||
dbgln("(STUBBED) HTMLFormElement::check_validity(). Called on: {}", debug_description());
|
||||
return true;
|
||||
return statically_validate_constraints().result;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-reportvalidity
|
||||
|
|
|
@ -78,6 +78,12 @@ public:
|
|||
GC::Ref<HTMLFormControlsCollection> elements() 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> report_validity();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue