1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-03 00:52:12 +00:00

LibWeb: Implement a slow but functional HTMLCollection :^)

HTMLCollection is an awkward legacy interface from the DOM spec.

It provides a live view of a DOM subtree, with some kind of filtering
that determines which elements are part of the collection.

We now return HTMLCollection objects from these APIs:

- getElementsByClassName()
- getElementsByName()
- getElementsByTagName()

This initial implementation does not do any kind of caching, since that
is quite a tricky problem, and there will be plenty of time for tricky
problems later on when the engine is more mature.
This commit is contained in:
Andreas Kling 2021-04-22 21:11:20 +02:00
parent 49f3d88baf
commit e4df1b223f
14 changed files with 207 additions and 55 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -14,6 +14,7 @@
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/DOM/ExceptionOr.h>
#include <LibWeb/DOM/HTMLCollection.h>
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/DOM/Text.h>
#include <LibWeb/HTML/Parser/HTMLDocumentParser.h>
@ -325,31 +326,22 @@ bool Element::is_focused() const
return document().focused_element() == this;
}
NonnullRefPtrVector<Element> Element::get_elements_by_tag_name(const FlyString& tag_name) const
NonnullRefPtr<HTMLCollection> Element::get_elements_by_tag_name(FlyString const& tag_name)
{
// FIXME: Support "*" for tag_name
// https://dom.spec.whatwg.org/#concept-getelementsbytagname
NonnullRefPtrVector<Element> elements;
for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
if (element.namespace_() == Namespace::HTML
? element.local_name().to_lowercase() == tag_name.to_lowercase()
: element.local_name() == tag_name) {
elements.append(element);
}
return IterationDecision::Continue;
return HTMLCollection::create(*this, [tag_name](Element const& element) {
if (element.namespace_() == Namespace::HTML)
return element.local_name().to_lowercase() == tag_name.to_lowercase();
return element.local_name() == tag_name;
});
return elements;
}
NonnullRefPtrVector<Element> Element::get_elements_by_class_name(const FlyString& class_name) const
NonnullRefPtr<HTMLCollection> Element::get_elements_by_class_name(FlyString const& class_name)
{
NonnullRefPtrVector<Element> elements;
for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
if (element.has_class(class_name, m_document->in_quirks_mode() ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive))
elements.append(element);
return IterationDecision::Continue;
return HTMLCollection::create(*this, [class_name, quirks_mode = document().in_quirks_mode()](Element const& element) {
return element.has_class(class_name, quirks_mode ? CaseSensitivity::CaseInsensitive : CaseSensitivity::CaseSensitive);
});
return elements;
}
void Element::set_shadow_root(RefPtr<ShadowRoot> shadow_root)