# DOM and Events

> lifecycle.root, query, queryAll, on and guard — scoped DOM access and managed event listeners for section scripts.

Canonical URL: https://77865786950d:3005/scripting/dom-and-events

Section scripts may only touch their own section. These members keep queries
and listeners inside it and skip anything owned by an island nested in the
section.

## lifecycle.root

`HTMLElement`. The section wrapper: `[data-section-id]` on pages, the
`[data-cart-custom-module]` wrapper in cart modules. All scoping below is
relative to it.

## lifecycle.query

```ts
lifecycle.query<T extends HTMLElement>(selector: string): T | null
```

The first match inside `root`, or `null`. A match inside a nested island
returns `null`.

```js
const total = lifecycle.query("[data-total]");
```

Use this instead of `document.querySelector(...)`, which the compiler rejects
as `global_dom_query`.

## lifecycle.queryAll

```ts
lifecycle.queryAll<T extends HTMLElement>(selector: string): T[]
```

Every match inside `root` as an array, excluding elements inside nested
islands.

```js
for (const tab of lifecycle.queryAll("[role=tab]")) tab.tabIndex = -1;
```

## lifecycle.on

```ts
lifecycle.on(
  target: EventTarget,
  type: string,
  listener: EventListenerOrEventListenerObject,
  options?: AddEventListenerOptions | boolean,
): () => void
```

Adds an event listener and returns a function that removes it. The listener is
removed automatically when the section stops.

- A DOM node outside `root`, or inside a nested island, throws
  `Section listeners cannot target outside the section or inside an island`.
- Non-node targets such as `window` are allowed, e.g. for `resize` or
  `lx:storage`.
- The listener runs on the [callback budget](/scripting/timers-and-observers#watchdog).

```js
const off = lifecycle.on(window, "resize", () => layout());
// later: off();
```

## lifecycle.guard

```ts
lifecycle.guard<TArgs extends unknown[]>(
  callback: (...args: TArgs) => void,
): (...args: TArgs) => void
```

Wraps a callback so it runs on the callback budget. Use it for callbacks the
runtime doesn't create for you, such as a promise `.then` or a third-party
event emitter.

```js
lifecycle.fetch(url).then((r) => r.json()).then(lifecycle.guard(render));
```
