+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp
index 71d1f815af..acb117e87b 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp
@@ -62,6 +62,34 @@ void HTMLFormElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(element);
}
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission
+WebIDL::ExceptionOr HTMLFormElement::implicitly_submit_form()
+{
+ // If the user agent supports letting the user submit a form implicitly (for example, on some platforms hitting the
+ // "enter" key while a text control is focused implicitly submits the form), then doing so for a form, whose default
+ // button has activation behavior and is not disabled, must cause the user agent to fire a click event at that
+ // default button.
+ if (auto* default_button = this->default_button()) {
+ auto& default_button_element = default_button->form_associated_element_to_html_element();
+
+ if (default_button_element.has_activation_behavior() && default_button->enabled())
+ default_button_element.click();
+
+ return {};
+ }
+
+ // If the form has no submit button, then the implicit submission mechanism must perform the following steps:
+
+ // 1. If the form has more than one field that blocks implicit submission, then return.
+ if (number_of_fields_blocking_implicit_submission() > 1)
+ return {};
+
+ // 2. Submit the form element from the form element itself with userInvolvement set to "activation".
+ TRY(submit_form(*this, { .user_involvement = UserNavigationInvolvement::Activation }));
+
+ return {};
+}
+
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-submit
WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr submitter, SubmitFormOptions options)
{
@@ -1012,4 +1040,66 @@ WebIDL::ExceptionOr HTMLFormElement::named_item_value(FlyString const
return node;
}
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#default-button
+FormAssociatedElement* HTMLFormElement::default_button()
+{
+ // A form element's default button is the first submit button in tree order whose form owner is that form element.
+ FormAssociatedElement* default_button = nullptr;
+
+ root().for_each_in_subtree([&](auto& node) {
+ auto* form_associated_element = dynamic_cast(&node);
+ if (!form_associated_element)
+ return IterationDecision::Continue;
+
+ if (form_associated_element->form() == this && form_associated_element->is_submit_button()) {
+ default_button = form_associated_element;
+ return IterationDecision::Break;
+ }
+
+ return IterationDecision::Continue;
+ });
+
+ return default_button;
+}
+
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#field-that-blocks-implicit-submission
+size_t HTMLFormElement::number_of_fields_blocking_implicit_submission() const
+{
+ // For the purpose of the previous paragraph, an element is a field that blocks implicit submission of a form
+ // element if it is an input element whose form owner is that form element and whose type attribute is in one of
+ // the following states: Text, Search, Telephone, URL, Email, Password, Date, Month, Week, Time,
+ // Local Date and Time, Number.
+ size_t count = 0;
+
+ for (auto element : m_associated_elements) {
+ if (!is(*element))
+ continue;
+
+ auto const& input = static_cast(*element);
+ using enum HTMLInputElement::TypeAttributeState;
+
+ switch (input.type_state()) {
+ case Text:
+ case Search:
+ case Telephone:
+ case URL:
+ case Email:
+ case Password:
+ case Date:
+ case Month:
+ case Week:
+ case Time:
+ case LocalDateAndTime:
+ case Number:
+ ++count;
+ break;
+
+ default:
+ break;
+ }
+ };
+
+ return count;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h
index 4bb43e72cc..736e3b0890 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h
@@ -59,6 +59,7 @@ public:
UserNavigationInvolvement user_involvement = { UserNavigationInvolvement::None };
};
WebIDL::ExceptionOr submit_form(JS::NonnullGCPtr submitter, SubmitFormOptions);
+ WebIDL::ExceptionOr implicitly_submit_form();
void reset_form();
@@ -117,6 +118,9 @@ private:
ErrorOr mail_as_body(AK::URL parsed_action, Vector entry_list, EncodingTypeAttributeState encoding_type, String encoding, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement);
void plan_to_navigate_to(AK::URL url, Variant post_resource, JS::NonnullGCPtr target_navigable, Bindings::NavigationHistoryBehavior history_handling, UserNavigationInvolvement user_involvement);
+ FormAssociatedElement* default_button();
+ size_t number_of_fields_blocking_implicit_submission() const;
+
bool m_firing_submission_events { false };
// https://html.spec.whatwg.org/multipage/forms.html#locked-for-reset
diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
index 738c08ef13..3aa382b6e6 100644
--- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -816,10 +817,18 @@ bool EventHandler::handle_keydown(KeyCode key, u32 modifiers, u32 code_point)
m_browsing_context->set_cursor_position(DOM::Position::create(realm, node, (unsigned)node.data().bytes().size()));
return true;
}
- if (key == KeyCode::Key_Return && is(node.editable_text_node_owner())) {
- auto& input_element = static_cast(*node.editable_text_node_owner());
- input_element.commit_pending_changes();
- return true;
+ if (key == KeyCode::Key_Return) {
+ if (is(node.editable_text_node_owner())) {
+ auto& input_element = static_cast(*node.editable_text_node_owner());
+
+ if (auto* form = input_element.form()) {
+ form->implicitly_submit_form().release_value_but_fixme_should_propagate_errors();
+ return true;
+ }
+
+ input_element.commit_pending_changes();
+ return true;
+ }
}
// FIXME: Text editing shortcut keys (copy/paste etc.) should be handled here.
if (!should_ignore_keydown_event(code_point, modifiers)) {