summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdwin Hoksberg <mail@edwinhoksberg.nl>2022-02-15 20:41:51 +0100
committerTim Flynn <trflynn89@pm.me>2022-02-16 07:23:27 -0500
commitc646afc26c0cd73275c3c70d85afb01c5adcd878 (patch)
tree30c4a99a83be028e1ffe772a5521ea667dde07f0
parent70ede2825ed7c63d940787f8d349796ad2784f58 (diff)
downloadserenity-c646afc26c0cd73275c3c70d85afb01c5adcd878.zip
LibWeb: Support Element.closest(selectors)
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.cpp26
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.h1
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.idl1
3 files changed, 28 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp
index 9f42142c2d..9870fd4ca8 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.cpp
+++ b/Userland/Libraries/LibWeb/DOM/Element.cpp
@@ -358,6 +358,32 @@ DOM::ExceptionOr<bool> Element::matches(StringView selectors) const
return false;
}
+// https://dom.spec.whatwg.org/#dom-element-closest
+DOM::ExceptionOr<DOM::Element const*> Element::closest(StringView selectors) const
+{
+ auto maybe_selectors = parse_selector(CSS::ParsingContext(static_cast<ParentNode&>(const_cast<Element&>(*this))), selectors);
+ if (!maybe_selectors.has_value())
+ return DOM::SyntaxError::create("Failed to parse selector");
+
+ auto matches_selectors = [](CSS::SelectorList const& selector_list, Element const* element) {
+ for (auto& selector : selector_list) {
+ if (!SelectorEngine::matches(selector, *element))
+ return false;
+ }
+ return true;
+ };
+
+ auto const selector_list = maybe_selectors.release_value();
+ for (auto* element = this; element; element = element->parent_element()) {
+ if (!matches_selectors(selector_list, element))
+ continue;
+
+ return element;
+ }
+
+ return nullptr;
+}
+
ExceptionOr<void> Element::set_inner_html(String const& markup)
{
auto result = DOMParsing::inner_html_setter(*this, markup);
diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h
index 03a6fecff1..dec2c12879 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.h
+++ b/Userland/Libraries/LibWeb/DOM/Element.h
@@ -63,6 +63,7 @@ public:
RefPtr<DOMTokenList> const& class_list();
DOM::ExceptionOr<bool> matches(StringView selectors) const;
+ DOM::ExceptionOr<DOM::Element const*> closest(StringView selectors) const;
int client_top() const;
int client_left() const;
diff --git a/Userland/Libraries/LibWeb/DOM/Element.idl b/Userland/Libraries/LibWeb/DOM/Element.idl
index 3cf0b0f255..0569653dd0 100644
--- a/Userland/Libraries/LibWeb/DOM/Element.idl
+++ b/Userland/Libraries/LibWeb/DOM/Element.idl
@@ -25,6 +25,7 @@ interface Element : Node {
[SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
boolean matches(DOMString selectors);
+ Element? closest(DOMString selectors);
// legacy alias of .matches
[ImplementedAs=matches] boolean webkitMatchesSelector(DOMString selectors);