From 94c67c364dba038f2d54355aa17630aa5d0093ab Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 19 Feb 2024 00:21:27 -0500 Subject: [PATCH] LibWeb: Implement HTMLInputElement's selected coordinates When an button is clicked, we now send the (x,y) coordinates of the click event (relative to the image) along with the form submission data. Regarding the text test, we can currently only test this feature with dialogs. The headless-browser test infrastructure cannot yet handle the resulting navigation that would occur if we were to test with normal form submission. --- .../expected/HTML/form-image-submission.txt | 1 + .../input/HTML/form-image-submission.html | 34 +++++++++++++++++++ .../LibWeb/HTML/FormControlInfrastructure.cpp | 33 ++++++++++++++---- .../Libraries/LibWeb/HTML/HTMLFormElement.cpp | 18 +++++++--- .../LibWeb/HTML/HTMLInputElement.cpp | 9 +++-- .../Libraries/LibWeb/HTML/HTMLInputElement.h | 7 ++++ 6 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/HTML/form-image-submission.txt create mode 100644 Tests/LibWeb/Text/input/HTML/form-image-submission.html diff --git a/Tests/LibWeb/Text/expected/HTML/form-image-submission.txt b/Tests/LibWeb/Text/expected/HTML/form-image-submission.txt new file mode 100644 index 0000000000..5feee74756 --- /dev/null +++ b/Tests/LibWeb/Text/expected/HTML/form-image-submission.txt @@ -0,0 +1 @@ + 10,20 diff --git a/Tests/LibWeb/Text/input/HTML/form-image-submission.html b/Tests/LibWeb/Text/input/HTML/form-image-submission.html new file mode 100644 index 0000000000..602f3bc7d2 --- /dev/null +++ b/Tests/LibWeb/Text/input/HTML/form-image-submission.html @@ -0,0 +1,34 @@ + + + + + + +
+ + +
+
+ + diff --git a/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp b/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp index 7f782e9d53..f12b046c14 100644 --- a/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp +++ b/Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp @@ -88,13 +88,32 @@ WebIDL::ExceptionOr>> construct_entry_list(J // 2. If the field element is an input element whose type attribute is in the Image Button state, then: if (auto* input_element = dynamic_cast(control.ptr()); input_element && input_element->type_state() == HTMLInputElement::TypeAttributeState::ImageButton) { - // FIXME: 1. If the field element has a name attribute specified and its value is not the empty string, let name be that value followed by a single U+002E FULL STOP character (.). Otherwise, let name be the empty string. - // FIXME: 2. Let namex be the string consisting of the concatenation of name and a single U0078 LATIN SMALL LETTER X character (x). - // FIXME: 3. Let namey be the string consisting of the concatenation of name and a single U+0079 LATIN SMALL LETTER Y character (y). - // FIXME: 4. The field element is submitter, and before this algorithm was invoked the user indicated a coordinate. Let x be the x-component of the coordinate selected by the user, and let y be the y-component of the coordinate selected by the user. - // FIXME: 5. Create an entry with namex and x, and append it to entry list. - // FIXME: 6. Create an entry with namey and y, and append it to entry list. - // 7. Continue. + // 1. If the field element is not submitter, then continue. + if (input_element != submitter.ptr()) + continue; + + // 2. If the field element has a name attribute specified and its value is not the empty string, let name be + // that value followed by U+002E (.). Otherwise, let name be the empty string. + String name; + if (auto value = input_element->get_attribute(AttributeNames::name); value.has_value() && !value->is_empty()) + name = MUST(String::formatted("{}.", *value)); + + // 3. Let namex be the concatenation of name and U+0078 (x). + auto name_x = MUST(String::formatted("{}x", name)); + + // 4. Let namey be the concatenation of name and U+0079 (y). + auto name_y = MUST(String::formatted("{}y", name)); + + // 5. Let (x, y) be the selected coordinate. + auto [x, y] = input_element->selected_coordinate(); + + // 6. Create an entry with namex and x, and append it to entry list. + entry_list.append(XHR::FormDataEntry { .name = move(name_x), .value = MUST(String::number(x)) }); + + // 7. Create an entry with namey and y, and append it to entry list. + entry_list.append(XHR::FormDataEntry { .name = move(name_y), .value = MUST(String::number(y)) }); + + // 8. Continue. continue; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp index 8a8b9eb2d6..5512463c3a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp @@ -189,12 +189,22 @@ WebIDL::ExceptionOr HTMLFormElement::submit_form(JS::NonnullGCPtr result; - // FIXME: 4. If submitter is an input element whose type attribute is in the Image Button state, then: - // 1. Let (x, y) be the selected coordinate. - // 2. Set result to the concatenation of x, ",", and y. + // 4. If submitter is an input element whose type attribute is in the Image Button state, then: + if (is(*submitter)) { + auto const& input_element = static_cast(*submitter); + + if (input_element.type_state() == HTMLInputElement::TypeAttributeState::ImageButton) { + // 1. Let (x, y) be the selected coordinate. + auto [x, y] = input_element.selected_coordinate(); + + // 2. Set result to the concatenation of x, ",", and y. + result = MUST(String::formatted("{},{}", x, y)); + } + } // 5. Otherwise, if submitter has a value, then set result to that value. - result = submitter->get_attribute_value(AttributeNames::value); + if (!result.has_value()) + result = submitter->get_attribute_value(AttributeNames::value); // 6. Close the dialog subject with result. subject->close(move(result)); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index f4a14bcbd7..d623b19626 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -304,8 +305,12 @@ WebIDL::ExceptionOr HTMLInputElement::run_input_activation_behavior(DOM::E if (!document().is_fully_active()) return {}; - // FIXME: 3. If the user activated the control while explicitly selecting a coordinate, then set the element's selected - // coordinate to that coordinate. + // 3. If the user activated the control while explicitly selecting a coordinate, then set the element's selected + // coordinate to that coordinate. + if (event.is_trusted() && is(event)) { + auto const& mouse_event = static_cast(event); + m_selected_coordinate = { mouse_event.offset_x(), mouse_event.offset_y() }; + } // 4. Submit the element's form owner from the element with userInvolvement set to event's user navigation involvement. TRY(form->submit_form(*this, { .user_involvement = user_navigation_involvement(event) })); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index b85ed9d35c..4fa885efdf 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -104,6 +104,12 @@ public: unsigned size() const; WebIDL::ExceptionOr set_size(unsigned value); + struct SelectedCoordinate { + double x { 0.0 }; + double y { 0.0 }; + }; + SelectedCoordinate selected_coordinate() const { return m_selected_coordinate; } + JS::Object* value_as_date() const; WebIDL::ExceptionOr set_value_as_date(Optional> const&); @@ -252,6 +258,7 @@ private: JS::GCPtr image_data() const; JS::GCPtr m_image_request; + SelectedCoordinate m_selected_coordinate; Optional m_load_event_delayer;