LibWeb: Add sorting to Table row HTMLCollection

Add an optional sorting function to HTMLCollection. We use
insertion_sort as a stable sorting algorithm so tree order can be
maintained.
This commit is contained in:
Lorenz A 2025-10-26 05:28:48 +01:00 committed by Sam Atkins
parent 63503c1ad6
commit 924e4d2baa
Notes: github-actions[bot] 2025-12-09 09:27:57 +00:00
5 changed files with 287 additions and 17 deletions

View file

@ -398,14 +398,14 @@ GC::Ref<HTMLTableSectionElement> HTMLTableElement::create_t_body()
GC::Ref<DOM::HTMLCollection> HTMLTableElement::rows()
{
HTMLTableElement* table_node = this;
// FIXME: The elements in the collection must be ordered such that those elements whose parent is a thead are
// included first, in tree order, followed by those elements whose parent is either a table or tbody
// element, again in tree order, followed finally by those elements whose parent is a tfoot element,
// still in tree order.
// How do you sort HTMLCollection?
// The elements in the collection must be ordered such that those elements whose parent is a thead are included
// first, in tree order, followed by those elements whose parent is either a table or tbody element, again in tree
// order, followed finally by those elements whose parent is a tfoot element, still in tree order.
if (!m_rows) {
m_rows = DOM::HTMLCollection::create(*this, DOM::HTMLCollection::Scope::Descendants, [table_node](DOM::Element const& element) {
m_rows = DOM::HTMLCollection::create(
*this,
DOM::HTMLCollection::Scope::Descendants,
[table_node](DOM::Element const& element) {
// Only match TR elements which are:
// * children of the table element
// * children of the thead, tbody, or tfoot elements that are themselves children of the table element
@ -415,13 +415,29 @@ GC::Ref<DOM::HTMLCollection> HTMLTableElement::rows()
if (element.parent_element() == table_node)
return true;
if (element.parent_element() && (element.parent_element()->local_name() == TagNames::thead || element.parent_element()->local_name() == TagNames::tbody || element.parent_element()->local_name() == TagNames::tfoot)
&& element.parent()->parent() == table_node) {
if (element.parent_element() && element.parent_element()->local_name().is_one_of(TagNames::thead, TagNames::tbody, TagNames::tfoot) && element.parent()->parent() == table_node)
return true;
}
return false;
});
return false; },
[](Element const& a, Element const& b) -> bool {
auto static sort_priority = [](Element const& element) {
auto const& parent_tag = element.parent_element()->local_name();
if (parent_tag == TagNames::thead)
return 1;
if (parent_tag == TagNames::table || parent_tag == TagNames::tbody)
return 2;
if (parent_tag == TagNames::tfoot)
return 3;
VERIFY_NOT_REACHED();
};
auto prio_a = sort_priority(a);
auto prio_b = sort_priority(b);
if (prio_a != prio_b)
return prio_a < prio_b;
return false; });
}
return *m_rows;
}