diff --git a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp index f2e425762c..8236f2ce67 100644 --- a/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventDispatcher.cpp @@ -242,7 +242,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr target, Event& even bool is_activation_event = is(event) && event.type() == HTML::EventNames::click; // 5. If isActivationEvent is true and target has activation behavior, then set activationTarget to target. - if (is_activation_event && target->activation_behavior) + if (is_activation_event && target->has_activation_behavior()) activation_target = target; // 6. Let slottable be target, if target is a slottable and is assigned, and null otherwise. @@ -293,7 +293,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr target, Event& even if (is(parent) || (is(parent) && verify_cast(*target).root().is_shadow_including_inclusive_ancestor_of(verify_cast(*parent)))) { // 1. If isActivationEvent is true, event’s bubbles attribute is true, activationTarget is null, and parent has activation behavior, then set activationTarget to parent. - if (is_activation_event && event.bubbles() && !activation_target && parent->activation_behavior) + if (is_activation_event && event.bubbles() && !activation_target && parent->has_activation_behavior()) activation_target = parent; // 2. Append to an event path with event, parent, null, relatedTarget, touchTargets, and slot-in-closed-tree. @@ -309,7 +309,7 @@ bool EventDispatcher::dispatch(JS::NonnullGCPtr target, Event& even target = *parent; // 1. If isActivationEvent is true, activationTarget is null, and target has activation behavior, then set activationTarget to target. - if (is_activation_event && !activation_target && target->activation_behavior) + if (is_activation_event && !activation_target && target->has_activation_behavior()) activation_target = target; // 2. Append to an event path with event, parent, target, relatedTarget, touchTargets, and slot-in-closed-tree. diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp index aa9966701a..8e4e5719c2 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.cpp +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.cpp @@ -816,4 +816,13 @@ bool EventTarget::has_event_listeners() const return !m_event_listener_list.is_empty(); } +bool EventTarget::has_activation_behavior() const +{ + return false; +} + +void EventTarget::activation_behavior(Event const&) +{ +} + } diff --git a/Userland/Libraries/LibWeb/DOM/EventTarget.h b/Userland/Libraries/LibWeb/DOM/EventTarget.h index efb85e27d9..df1dbc6224 100644 --- a/Userland/Libraries/LibWeb/DOM/EventTarget.h +++ b/Userland/Libraries/LibWeb/DOM/EventTarget.h @@ -45,7 +45,8 @@ public: Vector> event_listener_list(); - Function activation_behavior; + virtual bool has_activation_behavior() const; + virtual void activation_behavior(Event const&); // NOTE: These only exist for checkbox and radio input elements. virtual void legacy_pre_activation_behavior() { } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index ce0dfc0cc4..10cabee8fc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp @@ -16,9 +16,6 @@ JS_DEFINE_ALLOCATOR(HTMLAnchorElement); HTMLAnchorElement::HTMLAnchorElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { - activation_behavior = [this](auto const& event) { - run_activation_behavior(event); - }; } HTMLAnchorElement::~HTMLAnchorElement() = default; @@ -47,7 +44,12 @@ WebIDL::ExceptionOr HTMLAnchorElement::set_hyperlink_element_utils_href(St return set_attribute(HTML::AttributeNames::href, move(href)); } -void HTMLAnchorElement::run_activation_behavior(Web::DOM::Event const&) +bool HTMLAnchorElement::has_activation_behavior() const +{ + return true; +} + +void HTMLAnchorElement::activation_behavior(Web::DOM::Event const&) { // The activation behavior of an a element element given an event event is: diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h index da49e6fc2d..c120323389 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h @@ -41,7 +41,8 @@ private: virtual void initialize(JS::Realm&) override; - void run_activation_behavior(Web::DOM::Event const&); + virtual bool has_activation_behavior() const override; + virtual void activation_behavior(Web::DOM::Event const&) override; // ^DOM::Element virtual void attribute_changed(FlyString const& name, Optional const& value) override; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp index 04bfe8bdfb..686350f93d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.cpp @@ -15,40 +15,6 @@ JS_DEFINE_ALLOCATOR(HTMLButtonElement); HTMLButtonElement::HTMLButtonElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { - // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour - activation_behavior = [this](auto&) { - // 1. If element is disabled, then return. - if (!enabled()) - return; - - // 2. If element does not have a form owner, then return. - if (!form()) - return; - - // 3. If element's node document is not fully active, then return. - if (!this->document().is_fully_active()) - return; - - // 4. Switch on element's type attribute's state: - switch (type_state()) { - case TypeAttributeState::Submit: - // Submit Button - // Submit element's form owner from element. - form()->submit_form(*this).release_value_but_fixme_should_propagate_errors(); - break; - case TypeAttributeState::Reset: - // Reset Button - // Reset element's form owner. - form()->reset_form(); - break; - case TypeAttributeState::Button: - // Button - // Do nothing. - break; - default: - VERIFY_NOT_REACHED(); - } - }; } HTMLButtonElement::~HTMLButtonElement() = default; @@ -101,4 +67,45 @@ DeprecatedString HTMLButtonElement::value() const return deprecated_attribute(AttributeNames::value); } +bool HTMLButtonElement::has_activation_behavior() const +{ + return true; +} + +void HTMLButtonElement::activation_behavior(DOM::Event const&) +{ + // https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:activation-behaviour + // 1. If element is disabled, then return. + if (!enabled()) + return; + + // 2. If element does not have a form owner, then return. + if (!form()) + return; + + // 3. If element's node document is not fully active, then return. + if (!this->document().is_fully_active()) + return; + + // 4. Switch on element's type attribute's state: + switch (type_state()) { + case TypeAttributeState::Submit: + // Submit Button + // Submit element's form owner from element. + form()->submit_form(*this).release_value_but_fixme_should_propagate_errors(); + break; + case TypeAttributeState::Reset: + // Reset Button + // Reset element's form owner. + form()->reset_form(); + break; + case TypeAttributeState::Button: + // Button + // Do nothing. + break; + default: + VERIFY_NOT_REACHED(); + } +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h index 7c27b8cc6f..c14ea61cd0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h @@ -67,6 +67,9 @@ public: virtual DeprecatedString value() const override; + virtual bool has_activation_behavior() const override; + virtual void activation_behavior(DOM::Event const&) override; + private: virtual bool is_html_button_element() const override { return true; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 4d3996903a..ba712c294a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -38,14 +38,6 @@ HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName q : HTMLElement(document, move(qualified_name)) , m_value(DeprecatedString::empty()) { - activation_behavior = [this](auto&) { - // The activation behavior for input elements are these steps: - - // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return. - - // 2. Run this element's input activation behavior, if any, and do nothing otherwise. - run_input_activation_behavior().release_value_but_fixme_should_propagate_errors(); - }; } HTMLInputElement::~HTMLInputElement() = default; @@ -1284,4 +1276,20 @@ bool HTMLInputElement::is_submit_button() const return type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::ImageButton; } + +bool HTMLInputElement::has_activation_behavior() const +{ + return true; +} + +void HTMLInputElement::activation_behavior(DOM::Event const&) +{ + // The activation behavior for input elements are these steps: + + // FIXME: 1. If this element is not mutable and is not in the Checkbox state and is not in the Radio state, then return. + + // 2. Run this element's input activation behavior, if any, and do nothing otherwise. + run_input_activation_behavior().release_value_but_fixme_should_propagate_errors(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index ac38766eb7..d11abcb842 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -149,6 +149,9 @@ public: JS::GCPtr placeholder_element() { return m_placeholder_element; } JS::GCPtr placeholder_element() const { return m_placeholder_element; } + virtual bool has_activation_behavior() const override; + virtual void activation_behavior(DOM::Event const&) override; + private: HTMLInputElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.cpp index 6e72fe544e..7dfc4a1e68 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.cpp @@ -15,22 +15,29 @@ JS_DEFINE_ALLOCATOR(HTMLSummaryElement); HTMLSummaryElement::HTMLSummaryElement(DOM::Document& document, DOM::QualifiedName qualified_name) : HTMLElement(document, move(qualified_name)) { - activation_behavior = [this](auto&) { - // The activation behavior of summary elements is to run the following steps: +} - // 1. If this summary element is not the summary for its parent details, then return. - if (!is_summary_for_its_parent_details()) - return; +bool HTMLSummaryElement::has_activation_behavior() const +{ + return true; +} - // 2. Let parent be this summary element's parent. - auto* parent = this->parent_element(); +void HTMLSummaryElement::activation_behavior(DOM::Event const&) +{ + // The activation behavior of summary elements is to run the following steps: - // 3. If the open attribute is present on parent, then remove it. Otherwise, set parent's open attribute to the empty string. - if (parent->has_attribute(HTML::AttributeNames::open)) - parent->remove_attribute(HTML::AttributeNames::open); - else - parent->set_attribute(HTML::AttributeNames::open, String {}).release_value_but_fixme_should_propagate_errors(); - }; + // 1. If this summary element is not the summary for its parent details, then return. + if (!is_summary_for_its_parent_details()) + return; + + // 2. Let parent be this summary element's parent. + auto* parent = this->parent_element(); + + // 3. If the open attribute is present on parent, then remove it. Otherwise, set parent's open attribute to the empty string. + if (parent->has_attribute(HTML::AttributeNames::open)) + parent->remove_attribute(HTML::AttributeNames::open); + else + parent->set_attribute(HTML::AttributeNames::open, String {}).release_value_but_fixme_should_propagate_errors(); } // https://html.spec.whatwg.org/multipage/interactive-elements.html#summary-for-its-parent-details diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.h index 991ed728bc..36c2862e0c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSummaryElement.h @@ -23,6 +23,9 @@ public: bool is_summary_for_its_parent_details(); + virtual bool has_activation_behavior() const override; + virtual void activation_behavior(DOM::Event const&) override; + private: HTMLSummaryElement(DOM::Document&, DOM::QualifiedName);