Jelajahi Sumber

LibWeb: Implement HTMLFormElement::reset

This patch sets up the necessary infrastructure for implementing reset
algorithms for form-associated controls.
Srikavin Ramkumar 2 tahun lalu
induk
melakukan
7cc6ffe5b7

+ 3 - 0
Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h

@@ -65,6 +65,9 @@ public:
 
     virtual HTMLElement& form_associated_element_to_html_element() = 0;
 
+    // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-form-reset-control
+    virtual void reset_algorithm() {};
+
 protected:
     FormAssociatedElement() = default;
     virtual ~FormAssociatedElement() = default;

+ 39 - 0
Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp

@@ -6,6 +6,7 @@
 
 #include <AK/StringBuilder.h>
 #include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/Event.h>
 #include <LibWeb/HTML/BrowsingContext.h>
 #include <LibWeb/HTML/EventNames.h>
 #include <LibWeb/HTML/HTMLButtonElement.h>
@@ -136,11 +137,49 @@ void HTMLFormElement::submit_form(JS::GCPtr<HTMLElement> submitter, bool from_su
         page->load(request);
 }
 
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#resetting-a-form
+void HTMLFormElement::reset_form()
+{
+    // 1. Let reset be the result of firing an event named reset at form, with the bubbles and cancelable attributes initialized to true.
+    auto reset_event = DOM::Event::create(realm(), HTML::EventNames::reset);
+    reset_event->set_bubbles(true);
+    reset_event->set_cancelable(true);
+
+    bool reset = dispatch_event(*reset_event);
+
+    // 2. If reset is true, then invoke the reset algorithm of each resettable element whose form owner is form.
+    if (reset) {
+        for (auto element : m_associated_elements) {
+            VERIFY(is<FormAssociatedElement>(*element));
+            auto& form_associated_element = dynamic_cast<FormAssociatedElement&>(*element);
+            if (form_associated_element.is_resettable())
+                form_associated_element.reset_algorithm();
+        }
+    }
+}
+
 void HTMLFormElement::submit()
 {
     submit_form(this, true);
 }
 
+// https://html.spec.whatwg.org/multipage/forms.html#dom-form-reset
+void HTMLFormElement::reset()
+{
+    // 1. If the form element is marked as locked for reset, then return.
+    if (m_locked_for_reset)
+        return;
+
+    // 2. Mark the form element as locked for reset.
+    m_locked_for_reset = true;
+
+    // 3. Reset the form element.
+    reset_form();
+
+    // 4. Unmark the form element as locked for reset.
+    m_locked_for_reset = false;
+}
+
 void HTMLFormElement::add_associated_element(Badge<FormAssociatedElement>, HTMLElement& element)
 {
     m_associated_elements.append(element);

+ 8 - 0
Userland/Libraries/LibWeb/HTML/HTMLFormElement.h

@@ -22,9 +22,14 @@ public:
 
     void submit_form(JS::GCPtr<HTMLElement> submitter, bool from_submit_binding = false);
 
+    void reset_form();
+
     // NOTE: This is for the JS bindings. Use submit_form instead.
     void submit();
 
+    // NOTE: This is for the JS bindings. Use submit_form instead.
+    void reset();
+
     void add_associated_element(Badge<FormAssociatedElement>, HTMLElement&);
     void remove_associated_element(Badge<FormAssociatedElement>, HTMLElement&);
 
@@ -38,6 +43,9 @@ private:
 
     bool m_firing_submission_events { false };
 
+    // https://html.spec.whatwg.org/multipage/forms.html#locked-for-reset
+    bool m_locked_for_reset { false };
+
     Vector<JS::GCPtr<HTMLElement>> m_associated_elements;
 
     JS::GCPtr<DOM::HTMLCollection> mutable m_elements;

+ 1 - 0
Userland/Libraries/LibWeb/HTML/HTMLFormElement.idl

@@ -11,6 +11,7 @@ interface HTMLFormElement : HTMLElement {
     [Reflect=novalidate] attribute boolean noValidate;
 
     undefined submit();
+    [CEReactions] undefined reset();
 
     // FIXME: Should be a HTMLFormControlsCollection
     [SameObject] readonly attribute HTMLCollection elements;