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
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) 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. // 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; m_dirty = true;
ask_for_a_reset(); 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 // https://html.spec.whatwg.org/multipage/form-elements.html#dom-option-value
String HTMLOptionElement::value() const String HTMLOptionElement::value() const
{ {

View file

@ -20,6 +20,7 @@ public:
bool selected() const { return m_selected; } bool selected() const { return m_selected; }
void set_selected(bool); void set_selected(bool);
void set_selected_internal(bool);
String value() const; String value() const;
WebIDL::ExceptionOr<void> set_value(String 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. // 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))); TRY(const_cast<HTMLOptionsCollection&>(*options()).add(move(element), move(before)));
// If the inserted element is the first and only element, mark it as selected update_selectedness(); // Not in spec
auto options = list_of_options();
if (options.size() == 1) {
options.at(0)->set_selected(true);
update_inner_text_element();
}
return {}; return {};
} }
@ -481,14 +476,7 @@ void HTMLSelectElement::form_associated_element_was_inserted()
// Wait until children are ready // Wait until children are ready
queue_an_element_task(HTML::Task::Source::Microtask, [this] { queue_an_element_task(HTML::Task::Source::Microtask, [this] {
// Select first option when no other option is selected update_selectedness();
if (selected_index() == -1) {
auto options = list_of_options();
if (options.size() > 0) {
options.at(0)->set_selected(true);
}
}
update_inner_text_element();
}); });
} }
@ -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 did_select_item(Optional<u32> const& id);
void update_selectedness();
private: private:
HTMLSelectElement(DOM::Document&, DOM::QualifiedName); HTMLSelectElement(DOM::Document&, DOM::QualifiedName);