diff --git a/Libraries/LibWeb/DOM/Document.idl b/Libraries/LibWeb/DOM/Document.idl index 0c4f46d1cc..a6610cd8d1 100644 --- a/Libraries/LibWeb/DOM/Document.idl +++ b/Libraries/LibWeb/DOM/Document.idl @@ -8,8 +8,12 @@ interface Document : Node { readonly attribute DOMString contentType; Element? getElementById(DOMString id); - Element? querySelector(DOMString selectors); ArrayFromVector getElementsByTagName(DOMString tagName); + + readonly attribute Element? firstElementChild; + readonly attribute Element? lastElementChild; + + Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); Element createElement(DOMString tagName); diff --git a/Libraries/LibWeb/DOM/DocumentFragment.idl b/Libraries/LibWeb/DOM/DocumentFragment.idl index 0b42cb9bfe..46e7d36dba 100644 --- a/Libraries/LibWeb/DOM/DocumentFragment.idl +++ b/Libraries/LibWeb/DOM/DocumentFragment.idl @@ -1,6 +1,10 @@ interface DocumentFragment : Node { Element? getElementById(DOMString id); + + readonly attribute Element? firstElementChild; + readonly attribute Element? lastElementChild; + Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); diff --git a/Libraries/LibWeb/DOM/Element.idl b/Libraries/LibWeb/DOM/Element.idl index d4499e5268..a68a86bc05 100644 --- a/Libraries/LibWeb/DOM/Element.idl +++ b/Libraries/LibWeb/DOM/Element.idl @@ -5,6 +5,9 @@ interface Element : Node { DOMString? getAttribute(DOMString qualifiedName); void setAttribute(DOMString qualifiedName, DOMString value); + readonly attribute Element? firstElementChild; + readonly attribute Element? lastElementChild; + Element? querySelector(DOMString selectors); ArrayFromVector querySelectorAll(DOMString selectors); diff --git a/Libraries/LibWeb/DOM/ParentNode.cpp b/Libraries/LibWeb/DOM/ParentNode.cpp index 4d668883db..42f435c19e 100644 --- a/Libraries/LibWeb/DOM/ParentNode.cpp +++ b/Libraries/LibWeb/DOM/ParentNode.cpp @@ -70,4 +70,14 @@ NonnullRefPtrVector ParentNode::query_selector_all(const StringView& se return elements; } +RefPtr ParentNode::first_element_child() +{ + return first_child_of_type(); +} + +RefPtr ParentNode::last_element_child() +{ + return last_child_of_type(); +} + } diff --git a/Libraries/LibWeb/DOM/ParentNode.h b/Libraries/LibWeb/DOM/ParentNode.h index 7783197f9d..cf8aa6ec86 100644 --- a/Libraries/LibWeb/DOM/ParentNode.h +++ b/Libraries/LibWeb/DOM/ParentNode.h @@ -38,6 +38,9 @@ public: template void for_each_child(F); + RefPtr first_element_child(); + RefPtr last_element_child(); + RefPtr query_selector(const StringView&); NonnullRefPtrVector query_selector_all(const StringView&); diff --git a/Libraries/LibWeb/TreeNode.h b/Libraries/LibWeb/TreeNode.h index c4c5999811..3cd4742137 100644 --- a/Libraries/LibWeb/TreeNode.h +++ b/Libraries/LibWeb/TreeNode.h @@ -255,6 +255,12 @@ public: return const_cast(this)->template first_child_of_type(); } + template + const U* last_child_of_type() const + { + return const_cast(this)->template last_child_of_type(); + } + template U* first_child_of_type() { @@ -265,6 +271,16 @@ public: return nullptr; } + template + U* last_child_of_type() + { + for (auto* child = last_child(); child; child = child->previous_sibling()) { + if (is(*child)) + return &downcast(*child); + } + return nullptr; + } + template const U* first_ancestor_of_type() const {