From 05e78dabdbceea46bae7dca52b63dc0a115e7b52 Mon Sep 17 00:00:00 2001 From: Bastiaan van der Plaat Date: Mon, 26 Feb 2024 19:12:32 +0100 Subject: [PATCH] LibWeb: Add textarea readonly support --- Tests/LibWeb/Text/expected/input-readonly.txt | 1 + .../Text/expected/textarea-readonly.txt | 1 + Tests/LibWeb/Text/input/input-readonly.html | 7 ++++++ .../LibWeb/Text/input/textarea-readonly.html | 7 ++++++ .../LibWeb/HTML/HTMLTextAreaElement.cpp | 22 ++++++++++++++----- .../LibWeb/HTML/HTMLTextAreaElement.h | 10 ++++++++- 6 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/input-readonly.txt create mode 100644 Tests/LibWeb/Text/expected/textarea-readonly.txt create mode 100644 Tests/LibWeb/Text/input/input-readonly.html create mode 100644 Tests/LibWeb/Text/input/textarea-readonly.html diff --git a/Tests/LibWeb/Text/expected/input-readonly.txt b/Tests/LibWeb/Text/expected/input-readonly.txt new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/Tests/LibWeb/Text/expected/input-readonly.txt @@ -0,0 +1 @@ + diff --git a/Tests/LibWeb/Text/expected/textarea-readonly.txt b/Tests/LibWeb/Text/expected/textarea-readonly.txt new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/Tests/LibWeb/Text/expected/textarea-readonly.txt @@ -0,0 +1 @@ + diff --git a/Tests/LibWeb/Text/input/input-readonly.html b/Tests/LibWeb/Text/input/input-readonly.html new file mode 100644 index 0000000000..b8ffa5084e --- /dev/null +++ b/Tests/LibWeb/Text/input/input-readonly.html @@ -0,0 +1,7 @@ + diff --git a/Tests/LibWeb/Text/input/textarea-readonly.html b/Tests/LibWeb/Text/input/textarea-readonly.html new file mode 100644 index 0000000000..106b8e011e --- /dev/null +++ b/Tests/LibWeb/Text/input/textarea-readonly.html @@ -0,0 +1,7 @@ + diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp index b41eb4990e..a3ec6d558b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.cpp @@ -85,7 +85,7 @@ i32 HTMLTextAreaElement::default_tab_index_value() const void HTMLTextAreaElement::reset_algorithm() { // The reset algorithm for textarea elements is to set the dirty value flag back to false, - m_dirty = false; + m_dirty_value = false; // and set the raw value of element to its child text content. m_raw_value = child_text_content(); @@ -132,7 +132,7 @@ void HTMLTextAreaElement::set_value(String const& value) m_raw_value = value; // 3. Set this element's dirty value flag to true. - m_dirty = true; + m_dirty_value = true; // FIXME: 4. If the new API value is different from oldAPIValue, then move the text entry cursor position to the end of the text control, unselecting any selected text and resetting the selection direction to "none". update_placeholder_visibility(); @@ -203,7 +203,7 @@ void HTMLTextAreaElement::create_shadow_tree_if_needed() MUST(element->append_child(*m_inner_text_element)); m_text_node = heap().allocate(realm(), document(), String {}); - m_text_node->set_always_editable(true); + handle_readonly_attribute(attribute(HTML::AttributeNames::readonly)); m_text_node->set_editable_text_node_owner(Badge {}, *this); // NOTE: If `children_changed()` was called before now, `m_raw_value` will hold the text content. // Otherwise, it will get filled in whenever that does get called. @@ -213,6 +213,16 @@ void HTMLTextAreaElement::create_shadow_tree_if_needed() update_placeholder_visibility(); } +// https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly +void HTMLTextAreaElement::handle_readonly_attribute(Optional const& maybe_value) +{ + // The readonly attribute is a boolean attribute that controls whether or not the user can edit the form control. When specified, the element is not mutable. + m_is_mutable = !maybe_value.has_value(); + + if (m_text_node) + m_text_node->set_always_editable(m_is_mutable); +} + void HTMLTextAreaElement::update_placeholder_visibility() { if (!m_placeholder_element) @@ -232,7 +242,7 @@ void HTMLTextAreaElement::children_changed() { // The children changed steps for textarea elements must, if the element's dirty value flag is false, // set the element's raw value to its child text content. - if (!m_dirty) { + if (!m_dirty_value) { m_raw_value = child_text_content(); if (m_text_node) m_text_node->set_text_content(m_raw_value); @@ -245,13 +255,15 @@ void HTMLTextAreaElement::form_associated_element_attribute_changed(FlyString co if (name == HTML::AttributeNames::placeholder) { if (m_placeholder_text_node) m_placeholder_text_node->set_data(value.value_or(String {})); + } else if (name == HTML::AttributeNames::readonly) { + handle_readonly_attribute(value); } } void HTMLTextAreaElement::did_edit_text_node(Badge) { // A textarea element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the raw value. - m_dirty = true; + m_dirty_value = true; update_placeholder_visibility(); } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h index df311814b2..e2d4837d79 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h @@ -94,6 +94,8 @@ private: void create_shadow_tree_if_needed(); + void handle_readonly_attribute(Optional const& value); + void update_placeholder_visibility(); JS::GCPtr m_placeholder_element; JS::GCPtr m_placeholder_text_node; @@ -101,7 +103,13 @@ private: JS::GCPtr m_inner_text_element; JS::GCPtr m_text_node; - bool m_dirty { false }; + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fe-dirty + bool m_dirty_value { false }; + + // https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element:concept-fe-mutable + bool m_is_mutable { true }; + + // https://html.spec.whatwg.org/multipage/form-elements.html#concept-textarea-raw-value String m_raw_value; };