docs
Loading...
Searching...
No Matches
Range.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_DOMRange.h>
10#include <Ultralight/dom/Node.h>
11
12#include <cstddef>
13#include <string>
14#include <utility>
15#include <vector>
16
17namespace ultralight {
18namespace dom {
19
20///
21/// A handle to a live range (a span of a page between two boundary points).
22///
23/// A Range works like the JavaScript %Range. Get one from Document::createRange() and point it at
24/// some content:
25///
26/// ```
27/// dom::Range range = document.createRange();
28/// range.selectNodeContents(para);
29/// std::string text = range.toString();
30/// dom::DOMRect box = range.getBoundingClientRect();
31/// ```
32///
33/// Copying a Range copies the handle, so both refer to the same range. Use cloneRange() to make
34/// an independent copy.
35///
36/// After its page goes away, a Range stops working like a dom::Element does (see that class).
37///
38/// ## Boundary Points
39///
40/// Each boundary point is a node plus an offset. In a text or comment node the offset counts
41/// UTF-16 code units. In any other node it counts children.
42///
43/// - **A new range starts at the document.** A boundary point in the document itself reads as an
44/// empty Node (the document is never a Node), so point the range at real content first.
45/// - **Boundary nodes must come from the range's own document.** A node from another document
46/// (eg, a subframe's) leaves the range unchanged (with dom::Checked, the call fails with a
47/// WrongDocumentError).
48///
49/// ## Live Updates
50///
51/// The range stays valid while the page changes. When nodes are inserted or removed, the library
52/// moves the boundary points to match. If a boundary point's node is removed, the point moves to
53/// where that node was in its parent.
54///
55/// Each live range adds a little work to every DOM change in its document, so destroy a Range once
56/// you're done with it.
57///
58class Range {
59 public:
60 ///
61 /// Which boundary points compareBoundaryPoints() compares (the web's Range.START_TO_START
62 /// constants).
63 ///
64 enum class CompareHow : uint8_t {
65 StartToStart = kULDOMRangeCompareHow_StartToStart, ///< Compare the two start points.
66 StartToEnd = kULDOMRangeCompareHow_StartToEnd, ///< This end vs the other's start.
67 EndToEnd = kULDOMRangeCompareHow_EndToEnd, ///< Compare the two end points.
68 EndToStart = kULDOMRangeCompareHow_EndToStart, ///< This start vs the other's end.
69 };
70
71 ///
72 /// Create an empty Range.
73 ///
74 Range() {}
75
76 ///
77 /// Copy constructor (both handles refer to the same range).
78 ///
79 /// @param other The Range to copy.
80 ///
81 Range(const Range& other)
82 : handle_(other.handle_ ? ulCreateDOMRangeRef(other.handle_) : nullptr) {}
83
84 ///
85 /// Move constructor (`other` becomes empty).
86 ///
87 /// @param other The Range to move from.
88 ///
89 Range(Range&& other) noexcept : handle_(other.handle_) { other.handle_ = nullptr; }
90
91 ///
92 /// Assignment (copies or moves).
93 ///
94 /// @param other The Range to assign from.
95 ///
96 /// @return Returns this Range.
97 ///
98 Range& operator=(Range other) noexcept {
99 std::swap(handle_, other.handle_);
100 return *this;
101 }
102
103 ///
104 /// Destroy this handle (the page isn't affected).
105 ///
106 ~Range() { ulDestroyDOMRange(handle_); }
107
108 ///
109 /// Whether or not this Range is valid (see IsAlive()).
110 ///
111 explicit operator bool() const { return IsAlive(); }
112
113 ///
114 /// Whether or not this Range is empty (it holds no handle).
115 ///
116 bool IsEmpty() const { return handle_ == nullptr; }
117
118 ///
119 /// Whether or not this Range is valid (it isn't empty and its page is still alive).
120 ///
121 /// @note Safe to call from any thread.
122 ///
123 bool IsAlive() const { return handle_ && ulDOMRangeIsAlive(handle_); }
124
125 // --- Boundary reads ---------------------------------------------------------------------
126
127 ///
128 /// Get the node that holds the range's start (startContainer).
129 ///
130 /// @return Returns the node (empty if the start is in the document itself).
131 ///
133 return Node::Adopt(ulDOMRangeGetStartContainer(handle_));
134 }
135
136 ///
137 /// Get the offset of the range's start in startContainer() (startOffset).
138 ///
139 size_t startOffset() const { return ulDOMRangeGetStartOffset(handle_); }
140
141 ///
142 /// Get the node that holds the range's end (endContainer).
143 ///
144 /// @return Returns the node (empty if the end is in the document itself).
145 ///
146 Node endContainer() const { return Node::Adopt(ulDOMRangeGetEndContainer(handle_)); }
147
148 ///
149 /// Get the offset of the range's end in endContainer() (endOffset).
150 ///
151 size_t endOffset() const { return ulDOMRangeGetEndOffset(handle_); }
152
153 ///
154 /// Whether or not the range's start and end are the same point (collapsed).
155 ///
156 /// @return Returns true if the range is collapsed (also for an empty Range or one whose page
157 /// is gone).
158 ///
159 bool collapsed() const { return ulDOMRangeGetCollapsed(handle_); }
160
161 ///
162 /// Get the deepest node that contains both boundary points (commonAncestorContainer).
163 ///
164 /// @return Returns the node (empty if it's the document itself).
165 ///
167 return Node::Adopt(ulDOMRangeGetCommonAncestorContainer(handle_));
168 }
169
170 // --- Boundary writes --------------------------------------------------------------------
171
172 ///
173 /// Set the range's start (setStart).
174 ///
175 /// If the new start is after the range's end, the range collapses to the new start.
176 ///
177 /// @param node The node for the new start (from this range's document).
178 ///
179 /// @param offset The offset in `node` (see Boundary Points above).
180 ///
181 /// @note Nothing changes if `offset` is past the end of `node`, `node` is a doctype, or `node`
182 /// is from another document.
183 ///
184 void setStart(const Node& node, size_t offset) const {
185 ulDOMRangeSetStart(handle_, node.raw(), offset, nullptr);
186 }
187
188 ///
189 /// Same as setStart(), but returns a Result with the reason for a failure (eg, an IndexSizeError
190 /// if `offset` is past the end of `node`).
191 ///
192 /// @return Returns success. Fails with an IndexSizeError if `offset` is past the end of `node`,
193 /// an InvalidNodeTypeError if `node` is a doctype, or a WrongDocumentError if `node` is
194 /// from another document.
195 ///
196 [[nodiscard]] Result<void> setStart(const Node& node, size_t offset, Checked_t) const {
197 if (IsEmpty() || node.IsEmpty())
198 return detail::EmptyHandleError();
199 detail::ErrorScope error;
200 if (ulDOMRangeSetStart(handle_, node.raw(), offset, error.out()))
201 return {};
202 return Unexpected<Error>(error.TakeError());
203 }
204
205 ///
206 /// Set the range's end (setEnd).
207 ///
208 /// If the new end is before the range's start, the range collapses to the new end.
209 ///
210 /// @param node The node for the new end (from this range's document).
211 ///
212 /// @param offset The offset in `node` (see Boundary Points above).
213 ///
214 /// @note Nothing changes if `offset` is past the end of `node`, `node` is a doctype, or `node`
215 /// is from another document.
216 ///
217 void setEnd(const Node& node, size_t offset) const {
218 ulDOMRangeSetEnd(handle_, node.raw(), offset, nullptr);
219 }
220
221 ///
222 /// Same as setEnd(), but returns a Result with the reason for a failure (eg, an IndexSizeError
223 /// if `offset` is past the end of `node`).
224 ///
225 /// @return Returns success. Fails with an IndexSizeError if `offset` is past the end of `node`,
226 /// an InvalidNodeTypeError if `node` is a doctype, or a WrongDocumentError if `node` is
227 /// from another document.
228 ///
229 [[nodiscard]] Result<void> setEnd(const Node& node, size_t offset, Checked_t) const {
230 if (IsEmpty() || node.IsEmpty())
231 return detail::EmptyHandleError();
232 detail::ErrorScope error;
233 if (ulDOMRangeSetEnd(handle_, node.raw(), offset, error.out()))
234 return {};
235 return Unexpected<Error>(error.TakeError());
236 }
237
238 ///
239 /// Collapse the range to its start or its end (collapse).
240 ///
241 /// @param to_start Pass true to collapse to the start and false to collapse to the end.
242 ///
243 void collapse(bool to_start = false) const { ulDOMRangeCollapse(handle_, to_start); }
244
245 ///
246 /// Make the range cover a whole node (selectNode).
247 ///
248 /// The range starts just before `node` and ends just after it, in `node`'s parent.
249 ///
250 /// @param node The node to cover (from this range's document).
251 ///
252 /// @note Nothing changes if `node` has no parent or is from another document.
253 ///
254 void selectNode(const Node& node) const { ulDOMRangeSelectNode(handle_, node.raw(), nullptr); }
255
256 ///
257 /// Same as selectNode(), but returns a Result with the reason for a failure (eg, an
258 /// InvalidNodeTypeError if `node` has no parent).
259 ///
260 /// @return Returns success. Fails with an InvalidNodeTypeError if `node` has no parent, or a
261 /// WrongDocumentError if `node` is from another document.
262 ///
263 [[nodiscard]] Result<void> selectNode(const Node& node, Checked_t) const {
264 if (IsEmpty() || node.IsEmpty())
265 return detail::EmptyHandleError();
266 detail::ErrorScope error;
267 if (ulDOMRangeSelectNode(handle_, node.raw(), error.out()))
268 return {};
269 return Unexpected<Error>(error.TakeError());
270 }
271
272 ///
273 /// Make the range cover everything inside a node (selectNodeContents).
274 ///
275 /// For an element that's all of its children. For a text or comment node it's all of its text.
276 ///
277 /// @param node The node whose contents to cover (from this range's document).
278 ///
279 /// @note Nothing changes if `node` is a doctype or is from another document.
280 ///
281 void selectNodeContents(const Node& node) const {
282 ulDOMRangeSelectNodeContents(handle_, node.raw(), nullptr);
283 }
284
285 ///
286 /// Same as selectNodeContents(), but returns a Result with the reason for a failure (eg, a
287 /// WrongDocumentError if `node` is from another document).
288 ///
289 /// @return Returns success. Fails with an InvalidNodeTypeError if `node` is a doctype, or a
290 /// WrongDocumentError if `node` is from another document.
291 ///
292 [[nodiscard]] Result<void> selectNodeContents(const Node& node, Checked_t) const {
293 if (IsEmpty() || node.IsEmpty())
294 return detail::EmptyHandleError();
295 detail::ErrorScope error;
296 if (ulDOMRangeSelectNodeContents(handle_, node.raw(), error.out()))
297 return {};
298 return Unexpected<Error>(error.TakeError());
299 }
300
301 // --- Comparison -------------------------------------------------------------------------
302
303 ///
304 /// Compare a boundary point of this range with one of another range (compareBoundaryPoints).
305 ///
306 /// @param how Which point of each range to compare (see CompareHow).
307 ///
308 /// @param other The range to compare with.
309 ///
310 /// @return Returns -1, 0, or 1 if this range's point is before, at, or after the other range's
311 /// point. Also returns 0 if the call fails (eg, the ranges are in different documents),
312 /// so use the dom::Checked overload to tell a failure from equal points.
313 ///
314 int compareBoundaryPoints(CompareHow how, const Range& other) const {
315 int result = 0;
316 ulDOMRangeCompareBoundaryPoints(handle_, static_cast<ULDOMRangeCompareHow>(how),
317 other.handle_, &result, nullptr);
318 return result;
319 }
320
321 ///
322 /// Same as compareBoundaryPoints(), but returns a Result with the reason for a failure (eg, a
323 /// WrongDocumentError if the ranges are in different documents).
324 ///
325 /// @return Returns -1, 0, or 1 if this range's point is before, at, or after the other range's
326 /// point. Fails with a WrongDocumentError if the two points aren't in the same tree
327 /// (eg, the ranges are in different documents).
328 ///
329 [[nodiscard]] Result<int> compareBoundaryPoints(CompareHow how, const Range& other,
330 Checked_t) const {
331 if (IsEmpty() || other.IsEmpty())
332 return detail::EmptyHandleError();
333 detail::ErrorScope error;
334 int result = 0;
335 if (ulDOMRangeCompareBoundaryPoints(handle_,
336 static_cast<ULDOMRangeCompareHow>(how),
337 other.handle_, &result, error.out()))
338 return result;
339 return Unexpected<Error>(error.TakeError());
340 }
341
342 // --- Contents ---------------------------------------------------------------------------
343
344 ///
345 /// Remove the range's contents from the page (deleteContents).
346 ///
347 /// Text at the edges of the range is trimmed, and the range collapses to where the contents were.
348 ///
349 void deleteContents() const { ulDOMRangeDeleteContents(handle_, nullptr); }
350
351 ///
352 /// Same as deleteContents(), but returns a Result with the reason for a failure.
353 ///
354 /// @return Returns success (it fails only when this range is empty or its page is gone).
355 ///
356 [[nodiscard]] Result<void> deleteContents(Checked_t) const {
357 if (IsEmpty())
358 return detail::EmptyHandleError();
359 detail::ErrorScope error;
360 if (ulDOMRangeDeleteContents(handle_, error.out()))
361 return {};
362 return Unexpected<Error>(error.TakeError());
363 }
364
365 ///
366 /// Move the range's contents out of the page into a new fragment (extractContents).
367 ///
368 /// A node that's only partly inside the range stays in the page without the covered part, and
369 /// the fragment gets a copy that holds that part. The range collapses to where the contents were.
370 ///
371 /// @return Returns the fragment (empty if the range contains a doctype or its page is gone, in
372 /// which case nothing is removed).
373 ///
375 return DocumentFragment::Adopt(ulDOMRangeExtractContents(handle_, nullptr));
376 }
377
378 ///
379 /// Same as extractContents(), but returns a Result with the reason for a failure (eg, a
380 /// HierarchyRequestError if the range contains a doctype).
381 ///
382 /// @return Returns the fragment. Fails with a HierarchyRequestError if the range contains a
383 /// doctype.
384 ///
386 if (IsEmpty())
387 return detail::EmptyHandleError();
388 detail::ErrorScope error;
389 if (ULDOMFragment fragment = ulDOMRangeExtractContents(handle_, error.out()))
390 return DocumentFragment::Adopt(fragment);
391 return Unexpected<Error>(error.TakeError());
392 }
393
394 ///
395 /// Copy the range's contents into a new fragment (cloneContents). The page doesn't change.
396 ///
397 /// @return Returns the fragment (empty if the range contains a doctype or its page is gone).
398 ///
400 return DocumentFragment::Adopt(ulDOMRangeCloneContents(handle_, nullptr));
401 }
402
403 ///
404 /// Same as cloneContents(), but returns a Result with the reason for a failure (eg, a
405 /// HierarchyRequestError if the range contains a doctype).
406 ///
407 /// @return Returns the fragment. Fails with a HierarchyRequestError if the range contains a
408 /// doctype.
409 ///
411 if (IsEmpty())
412 return detail::EmptyHandleError();
413 detail::ErrorScope error;
414 if (ULDOMFragment fragment = ulDOMRangeCloneContents(handle_, error.out()))
415 return DocumentFragment::Adopt(fragment);
416 return Unexpected<Error>(error.TakeError());
417 }
418
419 ///
420 /// Insert a node at the range's start (insertNode).
421 ///
422 /// If the start is inside a text node, the text node is split there. If the range is collapsed,
423 /// it grows to cover the inserted node.
424 ///
425 /// @param node The node to insert (from this range's document). If it already has a parent,
426 /// it's moved.
427 ///
428 /// @note Nothing is inserted if `node` can't go there (eg, the start is inside a comment, or
429 /// `node` contains the start) or `node` is from another document.
430 ///
431 void insertNode(const Node& node) const { ulDOMRangeInsertNode(handle_, node.raw(), nullptr); }
432
433 ///
434 /// Same as insertNode(), but returns a Result with the reason for a failure (eg, a
435 /// HierarchyRequestError if `node` can't go there).
436 ///
437 /// @return Returns success. Fails with a HierarchyRequestError if `node` can't go there (eg,
438 /// the start is inside a comment, or `node` contains the start), or a
439 /// WrongDocumentError if `node` is from another document.
440 ///
441 [[nodiscard]] Result<void> insertNode(const Node& node, Checked_t) const {
442 if (IsEmpty() || node.IsEmpty())
443 return detail::EmptyHandleError();
444 detail::ErrorScope error;
445 if (ulDOMRangeInsertNode(handle_, node.raw(), error.out()))
446 return {};
447 return Unexpected<Error>(error.TakeError());
448 }
449
450 ///
451 /// Create an independent copy of the range (cloneRange).
452 ///
453 /// @return Returns a new Range with the same boundary points. From then on, each range updates
454 /// on its own.
455 ///
456 Range cloneRange() const { return Range(ulDOMRangeCloneRange(handle_)); }
457
458 ///
459 /// Get the text the range covers (toString).
460 ///
461 /// @return Returns the text of the text nodes in the range (comments aren't included).
462 ///
463 std::string toString() const {
464 return detail::TakeString(ulDOMRangeToString(handle_));
465 }
466
467 // --- Geometry ---------------------------------------------------------------------------
468
469 ///
470 /// Get the smallest rectangle that contains everything the range covers (getBoundingClientRect).
471 ///
472 /// @return Returns the rectangle in the same viewport coordinates as
473 /// Element::getBoundingClientRect() (all zero if nothing in the range is displayed).
474 ///
475 /// @note This reads the layout, so it forces a synchronous style and layout pass if the document
476 /// has pending changes.
477 ///
479 ULDOMRect rect = ulDOMRangeGetBoundingClientRect(handle_);
480 return DOMRect { rect.x, rect.y, rect.width, rect.height };
481 }
482
483 ///
484 /// Get a rectangle for each box the range covers (getClientRects).
485 ///
486 /// Text that wraps gives one rectangle per line. An element that's fully inside the range adds
487 /// its own border box too.
488 ///
489 /// @return Returns the rectangles in document order, in the same viewport coordinates as
490 /// Element::getBoundingClientRect().
491 ///
492 /// @note This reads the layout, so it forces a synchronous style and layout pass if the document
493 /// has pending changes.
494 ///
495 std::vector<DOMRect> getClientRects() const {
496 // Each waist call walks the range's boxes after a layout update, so query into a
497 // local buffer first and pay a second walk only when a range spans more lines than it
498 // holds (rare: one rectangle per line is the common shape).
499 ULDOMRect local[8];
500 size_t count = ulDOMRangeGetClientRects(handle_, local, 8);
501 std::vector<DOMRect> rects;
502 rects.reserve(count);
503 if (count <= 8) {
504 for (size_t i = 0; i < count; i++)
505 rects.push_back(DOMRect { local[i].x, local[i].y, local[i].width, local[i].height });
506 return rects;
507 }
508 std::vector<ULDOMRect> raw_rects(count);
509 ulDOMRangeGetClientRects(handle_, raw_rects.data(), raw_rects.size());
510 for (const ULDOMRect& rect : raw_rects)
511 rects.push_back(DOMRect { rect.x, rect.y, rect.width, rect.height });
512 return rects;
513 }
514
515 // --- Interop with the C API (most embedders never touch raw handles) -----------------------
516
517 ///
518 /// Wrap a C handle you own, taking ownership of it.
519 ///
520 /// @param handle A handle from the C API that you would otherwise destroy with
521 /// ulDestroyDOMRange() (NULL gives an empty Range).
522 ///
523 /// @return Returns a Range that destroys `handle` when it's done.
524 ///
525 static Range Adopt(ULDOMRange handle) { return Range(handle); }
526
527 ///
528 /// Wrap a C handle you don't own, adding a reference.
529 ///
530 /// @param handle The borrowed handle (NULL gives an empty Range).
531 ///
532 /// @return Returns a Range with its own reference, so you can keep it as long as you like.
533 ///
534 static Range FromBorrowed(ULDOMRange handle) {
535 return Range(handle ? ulCreateDOMRangeRef(handle) : nullptr);
536 }
537
538 ///
539 /// Get the C handle, for passing to the `<Ultralight/CAPI/CAPI_DOMRange.h>` functions.
540 ///
541 /// @return Returns the handle (NULL for an empty Range). This Range still owns it, so don't
542 /// destroy it.
543 ///
544 ULDOMRange raw() const { return handle_; }
545
546 ///
547 /// Give up ownership of the C handle and return it. This Range becomes empty.
548 ///
549 /// @return Returns the handle. You must call ulDestroyDOMRange() when finished.
550 ///
551 ULDOMRange LeakRef() {
552 ULDOMRange handle = handle_;
553 handle_ = nullptr;
554 return handle;
555 }
556
557 protected:
558 explicit Range(ULDOMRange handle) : handle_(handle) {}
559
560 ULDOMRange handle_ = nullptr;
561};
562
563} // namespace dom
564} // namespace ultralight
A container for assembling DOM nodes off the page.
Definition DocumentFragment.h:43
static DocumentFragment Adopt(ULDOMFragment handle)
Wrap a C handle you own, taking ownership of it.
Definition DocumentFragment.h:229
A reference to an item in the DOM tree.
Definition Node.h:147
ULDOMNode raw() const
Get the C handle, for passing to the <Ultralight/CAPI/CAPI_DOMNode.h> functions.
Definition Node.h:539
static Node Adopt(ULDOMNode handle)
Wrap a C handle you own, taking ownership of it.
Definition Node.h:520
bool IsEmpty() const
Whether or not this Node is empty (it holds no handle).
Definition Node.h:216
size_t startOffset() const
Get the offset of the range's start in startContainer() (startOffset).
Definition Range.h:139
Result< DocumentFragment > cloneContents(Checked_t) const
Same as cloneContents(), but returns a Result with the reason for a failure (eg, a HierarchyRequestEr...
Definition Range.h:410
Range & operator=(Range other) noexcept
Assignment (copies or moves).
Definition Range.h:98
size_t endOffset() const
Get the offset of the range's end in endContainer() (endOffset).
Definition Range.h:151
static Range Adopt(ULDOMRange handle)
Wrap a C handle you own, taking ownership of it.
Definition Range.h:525
std::string toString() const
Get the text the range covers (toString).
Definition Range.h:463
DocumentFragment extractContents() const
Move the range's contents out of the page into a new fragment (extractContents).
Definition Range.h:374
ULDOMRange LeakRef()
Give up ownership of the C handle and return it.
Definition Range.h:551
void insertNode(const Node &node) const
Insert a node at the range's start (insertNode).
Definition Range.h:431
Result< void > selectNode(const Node &node, Checked_t) const
Same as selectNode(), but returns a Result with the reason for a failure (eg, an InvalidNodeTypeError...
Definition Range.h:263
Range cloneRange() const
Create an independent copy of the range (cloneRange).
Definition Range.h:456
Result< void > setStart(const Node &node, size_t offset, Checked_t) const
Same as setStart(), but returns a Result with the reason for a failure (eg, an IndexSizeError if offs...
Definition Range.h:196
void collapse(bool to_start=false) const
Collapse the range to its start or its end (collapse).
Definition Range.h:243
DOMRect getBoundingClientRect() const
Get the smallest rectangle that contains everything the range covers (getBoundingClientRect).
Definition Range.h:478
DocumentFragment cloneContents() const
Copy the range's contents into a new fragment (cloneContents).
Definition Range.h:399
Result< int > compareBoundaryPoints(CompareHow how, const Range &other, Checked_t) const
Same as compareBoundaryPoints(), but returns a Result with the reason for a failure (eg,...
Definition Range.h:329
ULDOMRange handle_
Definition Range.h:560
Result< DocumentFragment > extractContents(Checked_t) const
Same as extractContents(), but returns a Result with the reason for a failure (eg,...
Definition Range.h:385
Node startContainer() const
Get the node that holds the range's start (startContainer).
Definition Range.h:132
bool collapsed() const
Whether or not the range's start and end are the same point (collapsed).
Definition Range.h:159
void selectNode(const Node &node) const
Make the range cover a whole node (selectNode).
Definition Range.h:254
Range(Range &&other) noexcept
Move constructor (other becomes empty).
Definition Range.h:89
Result< void > setEnd(const Node &node, size_t offset, Checked_t) const
Same as setEnd(), but returns a Result with the reason for a failure (eg, an IndexSizeError if offset...
Definition Range.h:229
void selectNodeContents(const Node &node) const
Make the range cover everything inside a node (selectNodeContents).
Definition Range.h:281
ULDOMRange raw() const
Get the C handle, for passing to the <Ultralight/CAPI/CAPI_DOMRange.h> functions.
Definition Range.h:544
~Range()
Destroy this handle (the page isn't affected).
Definition Range.h:106
bool IsEmpty() const
Whether or not this Range is empty (it holds no handle).
Definition Range.h:116
bool IsAlive() const
Whether or not this Range is valid (it isn't empty and its page is still alive).
Definition Range.h:123
Range(const Range &other)
Copy constructor (both handles refer to the same range).
Definition Range.h:81
Result< void > deleteContents(Checked_t) const
Same as deleteContents(), but returns a Result with the reason for a failure.
Definition Range.h:356
std::vector< DOMRect > getClientRects() const
Get a rectangle for each box the range covers (getClientRects).
Definition Range.h:495
Result< void > selectNodeContents(const Node &node, Checked_t) const
Same as selectNodeContents(), but returns a Result with the reason for a failure (eg,...
Definition Range.h:292
void deleteContents() const
Remove the range's contents from the page (deleteContents).
Definition Range.h:349
Node endContainer() const
Get the node that holds the range's end (endContainer).
Definition Range.h:146
void setEnd(const Node &node, size_t offset) const
Set the range's end (setEnd).
Definition Range.h:217
static Range FromBorrowed(ULDOMRange handle)
Wrap a C handle you don't own, adding a reference.
Definition Range.h:534
int compareBoundaryPoints(CompareHow how, const Range &other) const
Compare a boundary point of this range with one of another range (compareBoundaryPoints).
Definition Range.h:314
Node commonAncestorContainer() const
Get the deepest node that contains both boundary points (commonAncestorContainer).
Definition Range.h:166
Range(ULDOMRange handle)
Definition Range.h:558
void setStart(const Node &node, size_t offset) const
Set the range's start (setStart).
Definition Range.h:184
Result< void > insertNode(const Node &node, Checked_t) const
Same as insertNode(), but returns a Result with the reason for a failure (eg, a HierarchyRequestError...
Definition Range.h:441
Range()
Create an empty Range.
Definition Range.h:74
CompareHow
Which boundary points compareBoundaryPoints() compares (the web's Range.START_TO_START constants).
Definition Range.h:64
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
A rectangle in CSS pixels, relative to the viewport (DOMRect).
Definition DOMRect.h:26