You can inspect, measure, and modify spans of page content directly from native code, using similar syntax to JavaScript.

Native code can also read the user's active selection (a caret or highlighted text), change what is selected, and react to selection changes.

## Ranges

A `dom::Range` spans a slice of the page, matching JavaScript's `Range`. Call `createRange()` to create one, point it at your content, and read its text:

```cpp
auto range = document.createRange();
range.selectNodeContents(document.getElementById("quote"));
std::string text = range.toString();
```

### Measuring Text on Screen

Call `getBoundingClientRect()` to get a single box around everything the range covers, or `getClientRects()` for a `std::vector` of boxes covering each line of wrapped text. Both return viewport CSS pixels (updating layout first if the page has pending changes):

```cpp
for (dom::DOMRect line : range.getClientRects())
  DrawUnderline(line);
```

### Setting the Boundaries

Use `selectNode()` to span an entire node, or `selectNodeContents()` to span its children. To set exact endpoints, call `setStart()` and `setEnd()` with an offset (which counts UTF-16 units inside text nodes and child nodes elsewhere):

```cpp
dom::Node text = document.getElementById("quote").firstChild();
range.setStart(text, 0);
range.setEnd(text, 5);
```

### Changing the Content

You can remove, extract, or duplicate the DOM nodes covered by a range:

| Call | What It Does |
| :--- | :--- |
| `deleteContents()` | Removes the covered content from the page |
| `extractContents()` | Moves the covered content into a new `dom::DocumentFragment` (a node only partly covered stays, minus the covered part) |
| `cloneContents()` | Copies the covered content into a new fragment and leaves the page alone |

Call `extractContents()` to pull the covered nodes into a reusable fragment:

```cpp
dom::DocumentFragment removed = range.extractContents();
```

### Keeping a Range

A range is live— its ends move automatically as the page changes to keep covering the same content. Use `cloneRange()` to make an independent copy:

```cpp
dom::Range saved = range.cloneRange();
```

> 👍 Let Ranges Go When You're Done
>
> Each live range adds a little work to every change to its page, so destroy it once you're done.

## The Selection

Calling `document.getSelection()` returns the page's active selection, representing either the caret or highlighted text. Call `toString()` to read the selected text, and check `isCollapsed()` to see whether anything is highlighted:

```cpp
dom::Selection selection = document.getSelection();
if (!selection.isCollapsed())
  ShowQuoteButton(selection.toString());
```

### Reacting to Changes

Each change to the selection fires a `selectionchange` event on the document. The library dispatches these events during a later `Renderer::Update()` (one event per change):

```cpp
document.addEventListener("selectionchange", [document] {
  UpdateQuoteButton(document.getSelection().toString());
});
```

### Selecting a Range

Call `removeAllRanges()` followed by `addRange()` to select a range (on its own, `addRange()` only grows an overlapping selection). You can also call `modify()` to move or extend the selection by words or lines, like using the arrow keys:

```cpp
selection.removeAllRanges();
selection.addRange(range);
```

> 📘 Selections in Text Fields
>
> The selection sees a text field from outside— its anchor and focus sit just outside the `<input>` or `<textarea>`, and it reads as collapsed. Use the field's `selectionStart` and `selectionEnd` instead (see [Forms and Inputs](/docs/2.0/forms-and-inputs)).

## Differences from JavaScript

While the C++ API mirrors browser DOM behavior closely, a few calls return snapshots instead of live references or handle cross-document nodes differently:

| JavaScript | C++ |
| :--- | :--- |
| `getRangeAt()` returns the selection's live range (changing it changes the selection) | Returns a copy |
| Selection calls with a node from another document throw | Ignored |
| `getClientRects()` returns a list | Returns a `std::vector` snapshot |
