diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-03-22 10:55:13 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-22 16:06:38 +0100 |
commit | 859a75fd4c362b1058aa6c2730f94e374cc08ec6 (patch) | |
tree | 688f31e9eb16a46c1d8c94616ac78d455aa529f9 /Userland/Libraries | |
parent | 31b24c2b297f603856b4850fb9568b5b91a75621 (diff) | |
download | serenity-859a75fd4c362b1058aa6c2730f94e374cc08ec6.zip |
LibWeb: Handle input element value setting & getting closer to the spec
We should not set the 'value' attribute when an input element's value is
changed (by the user or programmatically). Instead, we should track the
value internally and mark it with a dirty flag when it is changed.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp | 42 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/HTMLInputElement.h | 4 |
2 files changed, 36 insertions, 10 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index cb84f3cc87..27a2486ebb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -22,6 +22,7 @@ namespace Web::HTML { HTMLInputElement::HTMLInputElement(DOM::Document& document, DOM::QualifiedName qualified_name) : FormAssociatedElement(document, move(qualified_name)) + , m_value(String::empty()) { activation_behavior = [this](auto&) { // The activation behavior for input elements are these steps: @@ -117,6 +118,10 @@ void HTMLInputElement::run_input_activation_behavior() void HTMLInputElement::did_edit_text_node(Badge<BrowsingContext>) { + // An input element's dirty value flag must be set to true whenever the user interacts with the control in a way that changes the value. + m_value = value_sanitization_algorithm(m_text_node->data()); + m_dirty_value = true; + // NOTE: This is a bit ad-hoc, but basically implements part of "4.10.5.5 Common event behaviors" // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events queue_an_element_task(HTML::Task::Source::UserInteraction, [this] { @@ -132,22 +137,33 @@ void HTMLInputElement::did_edit_text_node(Badge<BrowsingContext>) }); } +// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value String HTMLInputElement::value() const { - if (m_text_node) - return m_text_node->data(); - return default_value(); + // Return the current value of the element. + return m_value; } +// https://html.spec.whatwg.org/multipage/input.html#dom-input-value-value void HTMLInputElement::set_value(String value) { - auto sanitised_value = value_sanitization_algorithm(move(value)); + // 1. Let oldValue be the element's value. + auto old_value = move(m_value); - if (m_text_node) { - m_text_node->set_data(sanitised_value); - return; - } - set_attribute(HTML::AttributeNames::value, sanitised_value); + // 2. Set the element's value to the new value. + // NOTE: This is done as part of step 4 below. + + // 3. Set the element's dirty value flag to true. + m_dirty_value = true; + + // 4. Invoke the value sanitization algorithm, if the element's type attribute's current state defines one. + m_value = value_sanitization_algorithm(move(value)); + + // 5. If the element's value (after applying the value sanitization algorithm) is different from oldValue, + // and the element has a text entry cursor position, move the text entry cursor position to the end of the + // text control, unselecting any selected text and resetting the selection direction to "none". + if (m_text_node && (m_value != old_value)) + m_text_node->set_data(m_value); } void HTMLInputElement::create_shadow_tree_if_needed() @@ -169,7 +185,7 @@ void HTMLInputElement::create_shadow_tree_if_needed() } auto shadow_root = adopt_ref(*new DOM::ShadowRoot(document(), *this)); - auto initial_value = attribute(HTML::AttributeNames::value); + auto initial_value = m_value; if (initial_value.is_null()) initial_value = String::empty(); auto element = document().create_element(HTML::TagNames::div).release_value(); @@ -207,6 +223,9 @@ void HTMLInputElement::parse_attribute(FlyString const& name, String const& valu set_checked(true, ChangeSource::Programmatic); } else if (name == HTML::AttributeNames::type) { m_type = parse_type_attribute(value); + } else if (name == HTML::AttributeNames::value) { + if (!m_dirty_value) + m_value = value_sanitization_algorithm(value); } } @@ -232,6 +251,9 @@ void HTMLInputElement::did_remove_attribute(FlyString const& name) // the user agent must set the checkedness of the element to false. if (!m_dirty_checkedness) set_checked(false, ChangeSource::Programmatic); + } else if (name == HTML::AttributeNames::value) { + if (!m_dirty_value) + m_value = String::empty(); } } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index 78935804b6..75ddaa1cf0 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -119,11 +119,15 @@ private: // https://html.spec.whatwg.org/multipage/input.html#concept-input-checked-dirty-flag bool m_dirty_checkedness { 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/input.html#the-input-element:legacy-pre-activation-behavior bool m_before_legacy_pre_activation_behavior_checked { false }; RefPtr<HTMLInputElement> m_legacy_pre_activation_behavior_checked_element_in_group; TypeAttributeState m_type { TypeAttributeState::Text }; + String m_value; }; } |