1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 16:48: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

@ -24,6 +24,7 @@
#include <LibWeb/DOM/ElementFactory.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/ExceptionOr.h>
#include <LibWeb/DOM/HTMLCollection.h>
#include <LibWeb/DOM/Range.h>
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/DOM/Text.h>
@ -484,42 +485,29 @@ void Document::set_hovered_node(Node* node)
invalidate_style();
}
NonnullRefPtrVector<Element> Document::get_elements_by_name(const String& name) const
NonnullRefPtr<HTMLCollection> Document::get_elements_by_name(String const& name)
{
NonnullRefPtrVector<Element> elements;
for_each_in_inclusive_subtree_of_type<Element>([&](auto& element) {
if (element.attribute(HTML::AttributeNames::name) == name)
elements.append(element);
return IterationDecision::Continue;
return HTMLCollection::create(*this, [name](Element const& element) {
return element.name() == name;
});
return elements;
}
NonnullRefPtrVector<Element> Document::get_elements_by_tag_name(const FlyString& tag_name) const
NonnullRefPtr<HTMLCollection> Document::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> Document::get_elements_by_class_name(const FlyString& class_name) const
NonnullRefPtr<HTMLCollection> Document::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, 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;
}
Color Document::link_color() const