mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-08-16 17:00:35 +03:00
LibWeb: Deduplicate the firing of input events in HTMLInputElement
Input elements without a defined user-interaction behavior need to fire an input event when the user changes the element's value in some way. This change moves the code to do this into its own function and adds some spec text to explain what is being done.
This commit is contained in:
parent
bd73dd316d
commit
a3d12e569c
Notes:
sideshowbarker
2024-07-17 03:05:16 +09:00
Author: https://github.com/tcl3 Commit: https://github.com/LadybirdBrowser/ladybird/commit/a3d12e569c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/265
@ -408,22 +408,11 @@ void HTMLInputElement::did_edit_text_node(Badge<Navigable>)
|
||||
|
||||
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<Color> 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<Color> 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<WebIDL::CallbackType>(*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)
|
||||
|
@ -255,6 +255,8 @@ private:
|
||||
void handle_readonly_attribute(Optional<String> const& value);
|
||||
WebIDL::ExceptionOr<void> 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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user