Skip to content

Commit 94c67c3

Browse files
trflynn89awesomekling
authored andcommitted
LibWeb: Implement HTMLInputElement's selected coordinates
When an <input type=image> 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.
1 parent 3630238 commit 94c67c3

File tree

6 files changed

+89
-13
lines changed

6 files changed

+89
-13
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10,20
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<head>
2+
<!--
3+
These style rules ensure the (x,y) coordinates clicked below are the same as the resulting
4+
coordinates in the form submission event.
5+
-->
6+
<style type="text/css">
7+
dialog {
8+
margin: 0;
9+
padding: 0;
10+
}
11+
</style>
12+
</head>
13+
14+
<dialog id="dialog" open>
15+
<form id="form" method="dialog">
16+
<input value="well hello friends!" />
17+
<input id="image" type="image" src="../../../Layout/input/120.png" />
18+
</form>
19+
</dialog>
20+
<script src="../include.js"></script>
21+
<script>
22+
asyncTest(done => {
23+
let dialog = document.getElementById("dialog");
24+
let image = document.getElementById("image");
25+
26+
dialog.addEventListener("close", e => {
27+
println(dialog.returnValue);
28+
done();
29+
});
30+
31+
const imageRect = image.getBoundingClientRect();
32+
internals.click(imageRect.x + 10, imageRect.y + 20);
33+
});
34+
</script>

Userland/Libraries/LibWeb/HTML/FormControlInfrastructure.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,32 @@ WebIDL::ExceptionOr<Optional<Vector<XHR::FormDataEntry>>> construct_entry_list(J
8888

8989
// 2. If the field element is an input element whose type attribute is in the Image Button state, then:
9090
if (auto* input_element = dynamic_cast<HTML::HTMLInputElement*>(control.ptr()); input_element && input_element->type_state() == HTMLInputElement::TypeAttributeState::ImageButton) {
91-
// 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.
92-
// FIXME: 2. Let namex be the string consisting of the concatenation of name and a single U0078 LATIN SMALL LETTER X character (x).
93-
// FIXME: 3. Let namey be the string consisting of the concatenation of name and a single U+0079 LATIN SMALL LETTER Y character (y).
94-
// 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.
95-
// FIXME: 5. Create an entry with namex and x, and append it to entry list.
96-
// FIXME: 6. Create an entry with namey and y, and append it to entry list.
97-
// 7. Continue.
91+
// 1. If the field element is not submitter, then continue.
92+
if (input_element != submitter.ptr())
93+
continue;
94+
95+
// 2. If the field element has a name attribute specified and its value is not the empty string, let name be
96+
// that value followed by U+002E (.). Otherwise, let name be the empty string.
97+
String name;
98+
if (auto value = input_element->get_attribute(AttributeNames::name); value.has_value() && !value->is_empty())
99+
name = MUST(String::formatted("{}.", *value));
100+
101+
// 3. Let namex be the concatenation of name and U+0078 (x).
102+
auto name_x = MUST(String::formatted("{}x", name));
103+
104+
// 4. Let namey be the concatenation of name and U+0079 (y).
105+
auto name_y = MUST(String::formatted("{}y", name));
106+
107+
// 5. Let (x, y) be the selected coordinate.
108+
auto [x, y] = input_element->selected_coordinate();
109+
110+
// 6. Create an entry with namex and x, and append it to entry list.
111+
entry_list.append(XHR::FormDataEntry { .name = move(name_x), .value = MUST(String::number(x)) });
112+
113+
// 7. Create an entry with namey and y, and append it to entry list.
114+
entry_list.append(XHR::FormDataEntry { .name = move(name_y), .value = MUST(String::number(y)) });
115+
116+
// 8. Continue.
98117
continue;
99118
}
100119

Userland/Libraries/LibWeb/HTML/HTMLFormElement.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,22 @@ WebIDL::ExceptionOr<void> HTMLFormElement::submit_form(JS::NonnullGCPtr<HTMLElem
189189
// 3. Let result be null.
190190
Optional<String> result;
191191

192-
// FIXME: 4. If submitter is an input element whose type attribute is in the Image Button state, then:
193-
// 1. Let (x, y) be the selected coordinate.
194-
// 2. Set result to the concatenation of x, ",", and y.
192+
// 4. If submitter is an input element whose type attribute is in the Image Button state, then:
193+
if (is<HTMLInputElement>(*submitter)) {
194+
auto const& input_element = static_cast<HTMLInputElement const&>(*submitter);
195+
196+
if (input_element.type_state() == HTMLInputElement::TypeAttributeState::ImageButton) {
197+
// 1. Let (x, y) be the selected coordinate.
198+
auto [x, y] = input_element.selected_coordinate();
199+
200+
// 2. Set result to the concatenation of x, ",", and y.
201+
result = MUST(String::formatted("{},{}", x, y));
202+
}
203+
}
195204

196205
// 5. Otherwise, if submitter has a value, then set result to that value.
197-
result = submitter->get_attribute_value(AttributeNames::value);
206+
if (!result.has_value())
207+
result = submitter->get_attribute_value(AttributeNames::value);
198208

199209
// 6. Close the dialog subject with result.
200210
subject->close(move(result));

Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <LibWeb/Namespace.h>
4040
#include <LibWeb/Page/Page.h>
4141
#include <LibWeb/UIEvents/EventNames.h>
42+
#include <LibWeb/UIEvents/MouseEvent.h>
4243
#include <LibWeb/WebIDL/DOMException.h>
4344
#include <LibWeb/WebIDL/ExceptionOr.h>
4445

@@ -304,8 +305,12 @@ WebIDL::ExceptionOr<void> HTMLInputElement::run_input_activation_behavior(DOM::E
304305
if (!document().is_fully_active())
305306
return {};
306307

307-
// FIXME: 3. If the user activated the control while explicitly selecting a coordinate, then set the element's selected
308-
// coordinate to that coordinate.
308+
// 3. If the user activated the control while explicitly selecting a coordinate, then set the element's selected
309+
// coordinate to that coordinate.
310+
if (event.is_trusted() && is<UIEvents::MouseEvent>(event)) {
311+
auto const& mouse_event = static_cast<UIEvents::MouseEvent const&>(event);
312+
m_selected_coordinate = { mouse_event.offset_x(), mouse_event.offset_y() };
313+
}
309314

310315
// 4. Submit the element's form owner from the element with userInvolvement set to event's user navigation involvement.
311316
TRY(form->submit_form(*this, { .user_involvement = user_navigation_involvement(event) }));

Userland/Libraries/LibWeb/HTML/HTMLInputElement.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ class HTMLInputElement final
104104
unsigned size() const;
105105
WebIDL::ExceptionOr<void> set_size(unsigned value);
106106

107+
struct SelectedCoordinate {
108+
double x { 0.0 };
109+
double y { 0.0 };
110+
};
111+
SelectedCoordinate selected_coordinate() const { return m_selected_coordinate; }
112+
107113
JS::Object* value_as_date() const;
108114
WebIDL::ExceptionOr<void> set_value_as_date(Optional<JS::Handle<JS::Object>> const&);
109115

@@ -252,6 +258,7 @@ class HTMLInputElement final
252258

253259
JS::GCPtr<DecodedImageData> image_data() const;
254260
JS::GCPtr<SharedImageRequest> m_image_request;
261+
SelectedCoordinate m_selected_coordinate;
255262

256263
Optional<DOM::DocumentLoadEventDelayer> m_load_event_delayer;
257264

0 commit comments

Comments
 (0)