summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-03-22 10:55:13 -0400
committerAndreas Kling <kling@serenityos.org>2022-03-22 16:06:38 +0100
commit859a75fd4c362b1058aa6c2730f94e374cc08ec6 (patch)
tree688f31e9eb16a46c1d8c94616ac78d455aa529f9 /Userland/Libraries
parent31b24c2b297f603856b4850fb9568b5b91a75621 (diff)
downloadserenity-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.cpp42
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.h4
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;
};
}