diff --git a/Tests/LibWeb/Text/expected/DOM/FormAssociatedElement-selection.txt b/Tests/LibWeb/Text/expected/DOM/FormAssociatedElement-selection.txt
index 85d6a68107..e1991cb4ef 100644
--- a/Tests/LibWeb/Text/expected/DOM/FormAssociatedElement-selection.txt
+++ b/Tests/LibWeb/Text/expected/DOM/FormAssociatedElement-selection.txt
@@ -15,4 +15,5 @@ select event fired: 6 6
text-input selectionStart: 6 selectionEnd: 6 selectionDirection: forward
select event fired: 6 6
text-input selectionStart: 6 selectionEnd: 6 selectionDirection: backward
+select event fired: 6 6
textarea selectionStart: 0 selectionEnd: 9 selectionDirection: none
diff --git a/Tests/LibWeb/Text/expected/HTML/FormAssociatedElement-set-selectionDirection.txt b/Tests/LibWeb/Text/expected/HTML/FormAssociatedElement-set-selectionDirection.txt
new file mode 100644
index 0000000000..b3386c9f5f
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/HTML/FormAssociatedElement-set-selectionDirection.txt
@@ -0,0 +1,2 @@
+select event fired for input
+select event fired for textarea
diff --git a/Tests/LibWeb/Text/input/HTML/FormAssociatedElement-set-selectionDirection.html b/Tests/LibWeb/Text/input/HTML/FormAssociatedElement-set-selectionDirection.html
new file mode 100644
index 0000000000..c2f4b26ca1
--- /dev/null
+++ b/Tests/LibWeb/Text/input/HTML/FormAssociatedElement-set-selectionDirection.html
@@ -0,0 +1,25 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
index 9a8b4ea3fc..aa43970d0d 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.cpp
@@ -366,6 +366,22 @@ void FormAssociatedTextControlElement::set_selection_direction(Optional
m_selection_direction = string_to_selection_direction(direction);
}
+// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
+WebIDL::ExceptionOr FormAssociatedTextControlElement::set_selection_direction_binding(Optional direction)
+{
+ // 1. If this element is an input element, and selectionDirection does not apply to this element,
+ // throw an "InvalidStateError" DOMException.
+ auto const& html_element = form_associated_element_to_html_element();
+ if (is(html_element)) {
+ auto const& input_element = static_cast(html_element);
+ if (!input_element.selection_direction_applies())
+ return WebIDL::InvalidStateError::create(input_element.realm(), "selectionDirection does not apply to element"_fly_string);
+ }
+
+ set_the_selection_range(m_selection_start, m_selection_end, string_to_selection_direction(direction));
+ return {};
+}
+
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setrangetext
WebIDL::ExceptionOr FormAssociatedTextControlElement::set_range_text(String const& replacement)
{
diff --git a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
index 5eb30e2f00..7f6714a30a 100644
--- a/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
+++ b/Userland/Libraries/LibWeb/HTML/FormAssociatedElement.h
@@ -149,6 +149,7 @@ public:
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
Optional selection_direction() const;
void set_selection_direction(Optional direction);
+ WebIDL::ExceptionOr set_selection_direction_binding(Optional direction);
SelectionDirection selection_direction_state() const { return m_selection_direction; }
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-setrangetext
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 801e18b5b8..df459fe4c3 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -2359,6 +2359,21 @@ bool HTMLInputElement::selection_or_range_applies() const
return selection_or_range_applies_for_type_state(type_state());
}
+// https://html.spec.whatwg.org/multipage/input.html#do-not-apply
+bool HTMLInputElement::selection_direction_applies() const
+{
+ switch (type_state()) {
+ case TypeAttributeState::Text:
+ case TypeAttributeState::Search:
+ case TypeAttributeState::Telephone:
+ case TypeAttributeState::URL:
+ case TypeAttributeState::Password:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool HTMLInputElement::has_selectable_text() const
{
// Potential FIXME: Date, Month, Week, Time and LocalDateAndTime are rendered as a basic text input for now,
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
index abd8a2c3ca..b021b2b33d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -204,10 +204,13 @@ public:
bool step_up_or_down_applies() const;
bool select_applies() const;
bool selection_or_range_applies() const;
+ bool selection_direction_applies() const;
bool has_selectable_text() const;
static bool selection_or_range_applies_for_type_state(TypeAttributeState);
+ Optional selection_direction_binding() { return selection_direction(); }
+
protected:
void selection_was_changed(size_t selection_start, size_t selection_end) override;
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.idl
index 04ad87bd96..4b260ba24d 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.idl
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.idl
@@ -60,7 +60,7 @@ interface HTMLInputElement : HTMLElement {
undefined select();
attribute unsigned long? selectionStart;
attribute unsigned long? selectionEnd;
- attribute DOMString? selectionDirection;
+ [ImplementedAs=selection_direction_binding] attribute DOMString? selectionDirection;
undefined setRangeText(DOMString replacement);
undefined setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve");
undefined setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
index f52e4de74e..9c555bbefd 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp
@@ -329,9 +329,10 @@ String HTMLTextAreaElement::selection_direction_binding() const
return selection_direction().value();
}
-void HTMLTextAreaElement::set_selection_direction_binding(String direction)
+void HTMLTextAreaElement::set_selection_direction_binding(String const& direction)
{
- set_selection_direction(direction);
+ // NOTE: The selectionDirection setter never returns an error for textarea elements.
+ MUST(static_cast(*this).set_selection_direction_binding(direction));
}
void HTMLTextAreaElement::create_shadow_tree_if_needed()
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
index ab0c300ff0..726c811978 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h
@@ -118,7 +118,7 @@ public:
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-textarea/input-selectiondirection
String selection_direction_binding() const;
- void set_selection_direction_binding(String direction);
+ void set_selection_direction_binding(String const& direction);
void set_dirty_value_flag(Badge, bool flag) { m_dirty_value = flag; }