LibWeb: Implement selectedness algorithm

Implement selectedness setting algorithm in HTMLSelectElement
This commit is contained in:
Timur Sultanov 2024-07-25 21:13:22 +04:00 committed by Sam Atkins
parent 9cbb3fac12
commit f4102b1dc9
Notes: github-actions[bot] 2024-07-26 08:16:49 +00:00
4 changed files with 65 additions and 15 deletions

View file

@ -135,12 +135,7 @@ WebIDL::ExceptionOr<void> HTMLSelectElement::add(HTMLOptionOrOptGroupElement ele
// Similarly, the add(element, before) method must act like its namesake method on that same options collection.
TRY(const_cast<HTMLOptionsCollection&>(*options()).add(move(element), move(before)));
// If the inserted element is the first and only element, mark it as selected
auto options = list_of_options();
if (options.size() == 1) {
options.at(0)->set_selected(true);
update_inner_text_element();
}
update_selectedness(); // Not in spec
return {};
}
@ -481,14 +476,7 @@ void HTMLSelectElement::form_associated_element_was_inserted()
// Wait until children are ready
queue_an_element_task(HTML::Task::Source::Microtask, [this] {
// Select first option when no other option is selected
if (selected_index() == -1) {
auto options = list_of_options();
if (options.size() > 0) {
options.at(0)->set_selected(true);
}
}
update_inner_text_element();
update_selectedness();
});
}
@ -558,4 +546,58 @@ void HTMLSelectElement::update_inner_text_element()
}
}
}
// https://html.spec.whatwg.org/multipage/form-elements.html#selectedness-setting-algorithm
void HTMLSelectElement::update_selectedness()
{
if (has_attribute(AttributeNames::multiple))
return;
// If element's multiple attribute is absent, and element's display size is 1,
if (size() == 1) {
bool has_selected_elements = false;
for (auto const& option_element : list_of_options()) {
if (option_element->selected()) {
has_selected_elements = true;
break;
}
}
// and no option elements in the element's list of options have their selectedness set to true,
if (!has_selected_elements) {
// then set the selectedness of the first option element in the list of options in tree order
// that is not disabled, if any, to true, and return.
for (auto const& option_element : list_of_options()) {
if (!option_element->disabled()) {
option_element->set_selected_internal(true);
update_inner_text_element();
return;
}
}
}
}
// If element's multiple attribute is absent,
// and two or more option elements in element's list of options have their selectedness set to true,
// then set the selectedness of all but the last option element with its selectedness set to true
// in the list of options in tree order to false.
int number_of_selected = 0;
for (auto const& option_element : list_of_options()) {
if (option_element->selected())
++number_of_selected;
}
// and two or more option elements in element's list of options have their selectedness set to true,
if (number_of_selected >= 2) {
// then set the selectedness of all but the last option element with its selectedness set to true
// in the list of options in tree order to false.
for (auto const& option_element : list_of_options()) {
if (number_of_selected == 1) {
break;
}
option_element->set_selected_internal(false);
--number_of_selected;
}
}
update_inner_text_element();
}
}