docs
Loading...
Searching...
No Matches
ElementList.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5#pragma once
6#include <Ultralight/CAPI/CAPI_DOMElement.h>
8
9#include <cstddef>
10#include <utility>
11
12namespace ultralight {
13namespace dom {
14
15///
16/// A fixed list of DOM elements returned by a query or an Element::children() call.
17///
18/// Calls like dom::Document::querySelectorAll() and Element::children() return an ElementList to
19/// hold matching elements from a page. You use it in native code to inspect and update groups of
20/// elements, such as rows in a table or controls in a form.
21///
22/// Querying a table for rows and iterating over the results looks like this:
23///
24/// ```
25/// dom::ElementList scores = document.querySelectorAll("#scores tr");
26/// if (scores.empty())
27/// Log("no scores yet");
28///
29/// for (dom::Element score_row : scores)
30/// score_row.classList.add("visible");
31/// ```
32///
33/// ## Snapshot Behavior
34///
35/// An ElementList is a snapshot of elements at the time of the query, unlike live collections on
36/// the web. Later changes to the page never add, remove, or reorder entries in the list. Call
37/// dom::Document::querySelectorAll() again when you need the current elements.
38///
39/// Removing an element from the page leaves it in the list, and its handle stays valid. Collections
40/// like Element::children(), HTMLSelectElement::selectedOptions(), and HTMLFormElement::elements()
41/// are live on the web, but return snapshots in the library.
42///
43/// ## Usage and Lifetime
44///
45/// - **Check for no results with empty() or length().** An ElementList has no boolean operator, so
46/// writing `if (list)` doesn't compile.
47/// - **An ElementList can't be copied.** Transfer ownership with `std::move` when storing a list in
48/// a member variable.
49/// - **An ElementList doesn't keep its page alive.** When the page navigates away, the list keeps
50/// its length, but operations on its Element%s fail safely (see dom::Element).
51///
52/// @see dom::Document::querySelectorAll(), dom::Element::querySelectorAll(),
53/// dom::Element::children(), dom::NodeList
54///
56 public:
57 ///
58 /// Create an empty ElementList (length() is 0).
59 ///
60 ElementList() = default;
61
62 ElementList(const ElementList&) = delete;
64
65 ///
66 /// Move constructor (`other` becomes empty).
67 ///
68 /// @param other The ElementList to move from.
69 ///
70 ElementList(ElementList&& other) noexcept : handle_(other.handle_) {
71 other.handle_ = nullptr;
72 }
73
74 ///
75 /// Move assignment (destroys the current list and `other` becomes empty).
76 ///
77 /// @param other The ElementList to move from.
78 ///
79 /// @return Returns this ElementList.
80 ///
81 ElementList& operator=(ElementList&& other) noexcept {
82 if (this != &other) {
83 ulDestroyDOMElementList(handle_);
84 handle_ = other.handle_;
85 other.handle_ = nullptr;
86 }
87 return *this;
88 }
89
90 ///
91 /// Destroy the list (elements you got from it aren't affected).
92 ///
93 ~ElementList() { ulDestroyDOMElementList(handle_); }
94
95 ///
96 /// Get the number of elements in the list (length).
97 ///
98 /// @return Returns the number of elements (0 for an empty ElementList).
99 ///
100 size_t length() const { return ulDOMElementListGetLength(handle_); }
101
102 ///
103 /// Get the number of elements in the list (the same as length()).
104 ///
105 /// @return Returns the number of elements (0 for an empty ElementList).
106 ///
107 size_t size() const { return length(); }
108
109 ///
110 /// Whether or not the list has no elements (length() is 0).
111 ///
112 bool empty() const { return length() == 0; }
113
114 ///
115 /// Get the element at an index (item).
116 ///
117 /// @param index The zero-based index.
118 ///
119 /// @return Returns the element (empty if `index` is out of range).
120 ///
121 Element item(size_t index) const {
122 return Element::Adopt(ulDOMElementListGetElement(handle_, index));
123 }
124
125 ///
126 /// Get the element at an index (the same as item()).
127 ///
128 /// @param index The zero-based index.
129 ///
130 /// @return Returns the element (empty if `index` is out of range).
131 ///
132 Element operator[](size_t index) const { return item(index); }
133
134 ///
135 /// A forward iterator over the list's elements, so range-for works
136 /// (`for (dom::Element el : list)`).
137 ///
138 class iterator {
139 public:
140 iterator(const ElementList* list, size_t index) : list_(list), index_(index) {}
141
142 Element operator*() const { return list_->item(index_); }
144 ++index_;
145 return *this;
146 }
147 bool operator!=(const iterator& other) const { return index_ != other.index_; }
148 bool operator==(const iterator& other) const { return index_ == other.index_; }
149
150 private:
151 const ElementList* list_;
152 size_t index_;
153 };
154
155 iterator begin() const { return iterator(this, 0); }
156 iterator end() const { return iterator(this, length()); }
157
158 // --- Interop with the C API (most embedders never touch raw handles) -------------------
159
160 ///
161 /// Wrap a C handle you own, taking ownership of it.
162 ///
163 /// @param handle A handle from the C API that you would otherwise destroy with
164 /// ulDestroyDOMElementList() (NULL gives an empty ElementList).
165 ///
166 /// @return Returns an ElementList that destroys `handle` when it's done.
167 ///
168 static ElementList Adopt(ULDOMElementList handle) { return ElementList(handle); }
169
170 ///
171 /// Get the C handle, for passing to the `<Ultralight/CAPI/CAPI_DOMElement.h>` functions.
172 ///
173 /// @return Returns the handle (NULL for an empty ElementList). This ElementList still owns it,
174 /// so don't destroy it.
175 ///
176 ULDOMElementList raw() const { return handle_; }
177
178 ///
179 /// Give up ownership of the C handle and return it. This ElementList becomes empty.
180 ///
181 /// @return Returns the handle. You must call ulDestroyDOMElementList() when finished.
182 ///
183 ULDOMElementList LeakRef() {
184 ULDOMElementList handle = handle_;
185 handle_ = nullptr;
186 return handle;
187 }
188
189 protected:
190 explicit ElementList(ULDOMElementList handle) : handle_(handle) {}
191
192 private:
193 ULDOMElementList handle_ = nullptr;
194};
195
196inline ElementList Element::querySelectorAll(std::string_view selectors) const {
197 detail::CString s(selectors);
198 return ElementList::Adopt(ulDOMElementQuerySelectorAll(raw(), s.c_str(), nullptr));
199}
200
201inline Result<ElementList> Element::querySelectorAll(std::string_view selectors,
202 Checked_t) const {
203 if (IsEmpty())
204 return detail::EmptyHandleError();
205 detail::CString s(selectors);
206 detail::ErrorScope error;
207 ULDOMElementList result
208 = ulDOMElementQuerySelectorAll(raw(), s.c_str(), error.out());
209 if (result)
210 return ElementList::Adopt(result);
211 return Unexpected<Error>(error.TakeError());
212}
213
215 ULDOMElementList result = ulDOMElementGetSelectedOptions(raw());
216 return result ? ElementList::Adopt(result) : ElementList();
217}
218
220 ULDOMElementList result = ulDOMElementGetElements(raw());
221 return result ? ElementList::Adopt(result) : ElementList();
222}
223
225 ULDOMElementList result = ulDOMElementGetChildren(raw());
226 return result ? ElementList::Adopt(result) : ElementList();
227}
228
229} // namespace dom
230} // namespace ultralight
A handle to an element on a page.
Definition Element.h:142
static Element Adopt(ULDOMElement handle)
Wrap a C handle you own, taking ownership of it.
Definition Element.h:1987
ElementList querySelectorAll(std::string_view selectors) const
Find every element below this one that matches a CSS selector (querySelectorAll).
Definition ElementList.h:196
ElementList children() const
Get the element's child elements in order (children).
Definition ElementList.h:224
ULDOMElement raw() const
Get the C handle, for passing to the <Ultralight/CAPI/CAPI_DOMElement.h> functions.
Definition Element.h:2006
A forward iterator over the list's elements, so range-for works (for (dom::Element el : list)).
Definition ElementList.h:138
bool operator!=(const iterator &other) const
Definition ElementList.h:147
iterator(const ElementList *list, size_t index)
Definition ElementList.h:140
bool operator==(const iterator &other) const
Definition ElementList.h:148
iterator & operator++()
Definition ElementList.h:143
Element operator*() const
Definition ElementList.h:142
A fixed list of DOM elements returned by a query or an Element::children() call.
Definition ElementList.h:55
iterator begin() const
Definition ElementList.h:155
ElementList(const ElementList &)=delete
Element operator[](size_t index) const
Get the element at an index (the same as item()).
Definition ElementList.h:132
size_t size() const
Get the number of elements in the list (the same as length()).
Definition ElementList.h:107
static ElementList Adopt(ULDOMElementList handle)
Wrap a C handle you own, taking ownership of it.
Definition ElementList.h:168
~ElementList()
Destroy the list (elements you got from it aren't affected).
Definition ElementList.h:93
ULDOMElementList LeakRef()
Give up ownership of the C handle and return it.
Definition ElementList.h:183
bool empty() const
Whether or not the list has no elements (length() is 0).
Definition ElementList.h:112
ElementList(ULDOMElementList handle)
Definition ElementList.h:190
iterator end() const
Definition ElementList.h:156
size_t length() const
Get the number of elements in the list (length).
Definition ElementList.h:100
ElementList & operator=(const ElementList &)=delete
Element item(size_t index) const
Get the element at an index (item).
Definition ElementList.h:121
ElementList & operator=(ElementList &&other) noexcept
Move assignment (destroys the current list and other becomes empty).
Definition ElementList.h:81
ElementList()=default
Create an empty ElementList (length() is 0).
ULDOMElementList raw() const
Get the C handle, for passing to the <Ultralight/CAPI/CAPI_DOMElement.h> functions.
Definition ElementList.h:176
ElementList(ElementList &&other) noexcept
Move constructor (other becomes empty).
Definition ElementList.h:70
ElementList elements() const
Get the form's controls in document order (elements).
Definition ElementList.h:219
ElementList selectedOptions() const
Get the selected options in order (selectedOptions).
Definition ElementList.h:214
bool IsEmpty() const
Whether or not this Node is empty (it holds no handle).
Definition Node.h:216
Direct C++ access to modify page elements and handle events.
Expected< T, Error > Result
The result of a DOM operation that can fail (either a T or a dom::Error).
Definition Error.h:277
Root namespace for every public Ultralight type, function, and enumeration.
The type of dom::Checked.
Definition Error.h:282