diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp
index 4856a71739..c0d1c524a4 100644
--- a/Libraries/LibHTML/DOM/Document.cpp
+++ b/Libraries/LibHTML/DOM/Document.cpp
@@ -193,9 +193,9 @@ void Document::layout()
void Document::update_style()
{
for_each_in_subtree([&](Node& node) {
- if (!node.needs_style_update())
- return;
- to(node).recompute_style();
+ if (node.needs_style_update())
+ to(node).recompute_style();
+ return IterationDecision::Continue;
});
update_layout();
}
@@ -242,3 +242,27 @@ void Document::set_hovered_node(Node* node)
invalidate_style();
}
+
+const Element* Document::get_element_by_id(const String& id) const
+{
+ const Element* element = nullptr;
+ for_each_in_subtree([&](auto& node) {
+ if (is(node) && to(node).attribute("id") == id) {
+ element = &to(node);
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ });
+ return element;
+}
+
+Vector Document::get_elements_by_name(const String& name) const
+{
+ Vector elements;
+ for_each_in_subtree([&](auto& node) {
+ if (is(node) && to(node).attribute("name") == name)
+ elements.append(&to(node));
+ return IterationDecision::Continue;
+ });
+ return elements;
+}
diff --git a/Libraries/LibHTML/DOM/Document.h b/Libraries/LibHTML/DOM/Document.h
index dc3c6c625e..c7c7541748 100644
--- a/Libraries/LibHTML/DOM/Document.h
+++ b/Libraries/LibHTML/DOM/Document.h
@@ -80,6 +80,9 @@ public:
void schedule_style_update();
+ const Element* get_element_by_id(const String&) const;
+ Vector get_elements_by_name(const String&) const;
+
private:
virtual RefPtr create_layout_node(const StyleProperties* parent_style) const override;
diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp
index 8995a3e689..bebf6b23be 100644
--- a/Libraries/LibHTML/DOM/Node.cpp
+++ b/Libraries/LibHTML/DOM/Node.cpp
@@ -77,6 +77,7 @@ void Node::invalidate_style()
for_each_in_subtree([&](auto& node) {
if (is(node))
node.set_needs_style_update(true);
+ return IterationDecision::Continue;
});
document().schedule_style_update();
}
diff --git a/Libraries/LibHTML/HtmlView.cpp b/Libraries/LibHTML/HtmlView.cpp
index 4b755180e3..66eb4462d7 100644
--- a/Libraries/LibHTML/HtmlView.cpp
+++ b/Libraries/LibHTML/HtmlView.cpp
@@ -321,11 +321,14 @@ void HtmlView::scroll_to_anchor(const StringView& name)
HTMLAnchorElement* element = nullptr;
document()->for_each_in_subtree([&](auto& node) {
- if (!is(node))
- return;
- auto& anchor_element = to(node);
- if (anchor_element.name() == name)
- element = &anchor_element;
+ if (is(node)) {
+ auto& anchor_element = to(node);
+ if (anchor_element.name() == name) {
+ element = &anchor_element;
+ return IterationDecision::Break;
+ }
+ }
+ return IterationDecision::Continue;
});
if (!element) {
diff --git a/Libraries/LibHTML/TreeNode.h b/Libraries/LibHTML/TreeNode.h
index 229b07c4e2..d368b6c347 100644
--- a/Libraries/LibHTML/TreeNode.h
+++ b/Libraries/LibHTML/TreeNode.h
@@ -54,12 +54,27 @@ public:
bool is_child_allowed(const T&) const { return true; }
template
- void for_each_in_subtree(Callback callback)
+ IterationDecision for_each_in_subtree(Callback callback) const
{
- callback(static_cast(*this));
+ if (callback(static_cast(*this)) == IterationDecision::Break)
+ return IterationDecision::Break;
for (auto* child = first_child(); child; child = child->next_sibling()) {
- child->for_each_in_subtree(callback);
+ if (child->for_each_in_subtree(callback) == IterationDecision::Break)
+ return IterationDecision::Break;
}
+ return IterationDecision::Continue;
+ }
+
+ template
+ IterationDecision for_each_in_subtree(Callback callback)
+ {
+ if (callback(static_cast(*this)) == IterationDecision::Break)
+ return IterationDecision::Break;
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ if (child->for_each_in_subtree(callback) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
}
protected: