diff options
author | Edwin Hoksberg <mail@edwinhoksberg.nl> | 2022-02-15 20:41:51 +0100 |
---|---|---|
committer | Tim Flynn <trflynn89@pm.me> | 2022-02-16 07:23:27 -0500 |
commit | c646afc26c0cd73275c3c70d85afb01c5adcd878 (patch) | |
tree | 30c4a99a83be028e1ffe772a5521ea667dde07f0 | |
parent | 70ede2825ed7c63d940787f8d349796ad2784f58 (diff) | |
download | serenity-c646afc26c0cd73275c3c70d85afb01c5adcd878.zip |
LibWeb: Support Element.closest(selectors)
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.cpp | 26 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Element.idl | 1 |
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); |