LibWeb: Implement CSS validity pseudo-classes

This commit is contained in:
Psychpsyo 2025-02-02 20:41:23 +01:00 committed by Sam Atkins
parent 39e17e83f9
commit bad7324307
Notes: github-actions[bot] 2025-02-05 12:52:56 +00:00
15 changed files with 745 additions and 29 deletions

View file

@ -241,16 +241,21 @@ Vector<GC::Root<HTMLOptionElement>> HTMLSelectElement::list_of_options() const
void HTMLSelectElement::reset_algorithm()
{
update_cached_list_of_options();
// The reset algorithm for a select element selectElement is:
// The reset algorithm for select elements is to go through all the option elements in the element's list of options,
// 1. Set selectElement's user validity to false.
m_user_validity = false;
// 2. For each optionElement of selectElement's list of options:
for (auto const& option_element : m_cached_list_of_options) {
// set their selectedness to true if the option element has a selected attribute, and false otherwise,
// 1. If optionElement has a selected attribute, then set optionElement's selectedness to true; otherwise set it to false.
option_element->set_selected_internal(option_element->has_attribute(AttributeNames::selected));
// set their dirtiness to false,
// 2. Set optionElement's dirtiness to false.
option_element->m_dirty = false;
// and then have the option elements ask for a reset.
option_element->ask_for_a_reset();
}
// 3. Run the selectedness setting algorithm given selectElement.
update_selectedness();
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-selectedindex
@ -379,7 +384,8 @@ void HTMLSelectElement::queue_input_and_change_events()
{
// When the user agent is to send select update notifications, queue an element task on the user interaction task source given the select element to run these steps:
queue_an_element_task(HTML::Task::Source::UserInteraction, [this] {
// FIXME: 1. Set the select element's user interacted to true.
// 1. Set the select element's user validity to true.
m_user_validity = true;
// 2. Fire an event named input at the select element, with the bubbles and composed attributes initialized to true.
auto input_event = DOM::Event::create(realm(), HTML::EventNames::input);
@ -691,4 +697,28 @@ bool HTMLSelectElement::is_focusable() const
return enabled();
}
// https://html.spec.whatwg.org/multipage/form-elements.html#placeholder-label-option
HTMLOptionElement* HTMLSelectElement::placeholder_label_option() const
{
// If a select element has a required attribute specified, does not have a multiple attribute specified, and has a display size of 1;
if (has_attribute(HTML::AttributeNames::required) && !has_attribute(HTML::AttributeNames::multiple) && display_size() == 1) {
// and if the value of the first option element in the
// select element's list of options (if any) is the empty string, and that option element's parent node is the select element (and not an optgroup element), then that option is the
// select element's placeholder label option.
auto first_option_element = list_of_options()[0];
if (first_option_element->value().is_empty() && first_option_element->parent() == this)
return first_option_element;
}
return {};
}
// https://html.spec.whatwg.org/multipage/form-elements.html#the-select-element%3Asuffering-from-being-missing
bool HTMLSelectElement::suffering_from_being_missing() const
{
// If the element has its required attribute specified, and either none of the option elements in the select element's list of options have their selectedness
// set to true, or the only option element in the select element's list of options with its selectedness set to true is the placeholder label option, then the element is suffering from being
// missing.
return has_attribute(HTML::AttributeNames::required) && (m_selected_options->length() == 0 || (m_selected_options->length() == 1 && m_selected_options->item(0) == placeholder_label_option()));
}
}