diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
index 34674e8119e..25370c2965e 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp
@@ -408,22 +408,11 @@ void HTMLInputElement::did_edit_text_node(Badge)
update_placeholder_visibility();
- // 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] {
- auto input_event = DOM::Event::create(realm(), HTML::EventNames::input);
- input_event->set_bubbles(true);
- input_event->set_composed(true);
- dispatch_event(*input_event);
- });
+ user_interaction_did_change_input_value();
}
void HTMLInputElement::did_pick_color(Optional picked_color, ColorPickerUpdateState state)
{
- // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
- // For input elements without a defined input activation behavior, but to which these events apply
- // and for which the user interface involves both interactive manipulation and an explicit commit action
-
if (type_state() == TypeAttributeState::Color && picked_color.has_value()) {
// then when the user changes the element's value
m_value = value_sanitization_algorithm(picked_color.value().to_string_without_alpha());
@@ -432,15 +421,10 @@ void HTMLInputElement::did_pick_color(Optional picked_color, ColorPickerU
update_color_well_element();
// the user agent must queue an element task on the user interaction task source
- queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
- // given the input element to fire an event named input at the input element, with the bubbles and composed attributes initialized to true
- auto input_event = DOM::Event::create(realm(), HTML::EventNames::input);
- input_event->set_bubbles(true);
- input_event->set_composed(true);
- dispatch_event(*input_event);
- });
+ user_interaction_did_change_input_value();
- // and any time the user commits the change, the user agent must queue an element task on the user interaction task source
+ // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
+ // [...] any time the user commits the change, the user agent must queue an element task on the user interaction task source
if (state == ColorPickerUpdateState::Closed) {
queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
// given the input element
@@ -980,18 +964,8 @@ void HTMLInputElement::create_range_input_shadow_tree()
MUST(slider_runnable_track->append_child(*m_slider_thumb));
update_slider_thumb_element();
- // User event listeners
- auto dispatch_input_event = [this]() {
- queue_an_element_task(HTML::Task::Source::UserInteraction, [&] {
- auto input_event = DOM::Event::create(realm(), HTML::EventNames::input);
- input_event->set_bubbles(true);
- input_event->set_composed(true);
- dispatch_event(*input_event);
- });
- };
-
auto keydown_callback_function = JS::NativeFunction::create(
- realm(), [this, dispatch_input_event](JS::VM& vm) {
+ realm(), [this](JS::VM& vm) {
auto key = MUST(vm.argument(0).get(vm, "key")).as_string().utf8_string();
if (key == "ArrowLeft" || key == "ArrowDown")
@@ -1004,7 +978,7 @@ void HTMLInputElement::create_range_input_shadow_tree()
if (key == "PageUp")
MUST(step_up(10));
- dispatch_input_event();
+ user_interaction_did_change_input_value();
return JS::js_undefined();
},
0, "", &realm());
@@ -1012,28 +986,28 @@ void HTMLInputElement::create_range_input_shadow_tree()
add_event_listener_without_options(UIEvents::EventNames::keydown, DOM::IDLEventListener::create(realm(), keydown_callback));
auto wheel_callback_function = JS::NativeFunction::create(
- realm(), [this, dispatch_input_event](JS::VM& vm) {
+ realm(), [this](JS::VM& vm) {
auto deltaY = MUST(vm.argument(0).get(vm, "deltaY")).as_i32();
if (deltaY > 0) {
MUST(step_down());
} else {
MUST(step_up());
}
- dispatch_input_event();
+ user_interaction_did_change_input_value();
return JS::js_undefined();
},
0, "", &realm());
auto wheel_callback = realm().heap().allocate_without_realm(*wheel_callback_function, Bindings::host_defined_environment_settings_object(realm()));
add_event_listener_without_options(UIEvents::EventNames::wheel, DOM::IDLEventListener::create(realm(), wheel_callback));
- auto update_slider_by_mouse = [this, dispatch_input_event](JS::VM& vm) {
+ auto update_slider_by_mouse = [this](JS::VM& vm) {
auto client_x = MUST(vm.argument(0).get(vm, "clientX")).as_double();
auto rect = get_bounding_client_rect();
double minimum = *min();
double maximum = *max();
// FIXME: Snap new value to input steps
MUST(set_value_as_number(clamp(round(((client_x - rect->left()) / rect->width()) * (maximum - minimum) + minimum), minimum, maximum)));
- dispatch_input_event();
+ user_interaction_did_change_input_value();
};
auto mousedown_callback_function = JS::NativeFunction::create(
@@ -1070,6 +1044,23 @@ void HTMLInputElement::create_range_input_shadow_tree()
add_event_listener_without_options(UIEvents::EventNames::mousedown, DOM::IDLEventListener::create(realm(), mousedown_callback));
}
+void HTMLInputElement::user_interaction_did_change_input_value()
+{
+ // https://html.spec.whatwg.org/multipage/input.html#common-input-element-events
+ // For input elements without a defined input activation behavior, but to which these events apply,
+ // and for which the user interface involves both interactive manipulation and an explicit commit action,
+ // then when the user changes the element's value, the user agent must queue an element task on the user interaction task source
+ // given the input element to fire an event named input at the input element, with the bubbles and composed attributes initialized to true,
+ // and any time the user commits the change, the user agent must queue an element task on the user interaction task source given the input
+ // element to set its user validity to true and fire an event named change at the input element, with the bubbles attribute initialized to true.
+ queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
+ auto input_event = DOM::Event::create(realm(), HTML::EventNames::input);
+ input_event->set_bubbles(true);
+ input_event->set_composed(true);
+ dispatch_event(*input_event);
+ });
+}
+
void HTMLInputElement::update_slider_thumb_element()
{
if (!m_slider_thumb)
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
index 9ae84128f7d..5039bd91535 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h
@@ -255,6 +255,8 @@ private:
void handle_readonly_attribute(Optional const& value);
WebIDL::ExceptionOr handle_src_attribute(String const& value);
+ void user_interaction_did_change_input_value();
+
// https://html.spec.whatwg.org/multipage/input.html#value-sanitization-algorithm
String value_sanitization_algorithm(String const&) const;