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

@ -57,11 +57,16 @@ void HTMLOptionElement::attribute_changed(FlyString const& name, Optional<String
void HTMLOptionElement::set_selected(bool selected)
{
// On setting, it must set the element's selectedness to the new value, set its dirtiness to true, and then cause the element to ask for a reset.
m_selected = selected;
set_selected_internal(selected);
m_dirty = true;
ask_for_a_reset();
}
void HTMLOptionElement::set_selected_internal(bool selected)
{
m_selected = selected;
}
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
String HTMLOptionElement::value() const
{

View file

@ -20,6 +20,7 @@ public:
bool selected() const { return m_selected; }
void set_selected(bool);
void set_selected_internal(bool);
String value() const;
WebIDL::ExceptionOr<void> set_value(String const&);

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();
}
}

View file

@ -92,6 +92,8 @@ public:
void did_select_item(Optional<u32> const& id);
void update_selectedness();
private:
HTMLSelectElement(DOM::Document&, DOM::QualifiedName);