SpeechSynthesisVoice - Web APIs

SpeechSynthesisVoice
====================

 The **`SpeechSynthesisVoice`** interface of the Web Speech API represents a voice that the system supports.
 Every `SpeechSynthesisVoice` has its own relative speech service including information about language, name and URI.

Instance properties
-------------------

`SpeechSynthesisVoice.default` Read only

A boolean value indicating whether the voice is the default voice for the current app language (`true`), or not (`false`.)

`SpeechSynthesisVoice.lang` Read only

Returns a BCP 47 language tag indicating the language of the voice.

`SpeechSynthesisVoice.localService` Read only

A boolean value indicating whether the voice is supplied by a local speech synthesizer service (`true`), or a remote speech synthesizer service (`false`.)

`SpeechSynthesisVoice.name` Read only

Returns a human-readable name that represents the voice.

`SpeechSynthesisVoice.voiceURI` Read only

Returns the type of URI and location of the speech synthesis service for this voice.

Examples
--------

The following snippet is excerpted from our Speech synthesizer demo.

```js
const synth = window.speechSynthesis;
function populateVoiceList() {
  voices = synth.getVoices();

  for (let i = 0; i < voices.length; i++) {
    const option = document.createElement("option");
    option.textContent = `${voices[i].name} (${voices[i].lang})`;

    if (voices[i].default) {
      option.textContent += " — DEFAULT";
    }

    option.setAttribute("data-lang", voices[i].lang);
    option.setAttribute("data-name", voices[i].name);
    voiceSelect.appendChild(option);
  }
}

populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
  speechSynthesis.onvoiceschanged = populateVoiceList;
}

inputForm.onsubmit = (event) => {
  event.preventDefault();

  const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
  const selectedOption =
    voiceSelect.selectedOptions[0].getAttribute("data-name");
  for (let i = 0; i < voices.length; i++) {
    if (voices[i].name === selectedOption) {
      utterThis.voice = voices[i];
    }
  }
  utterThis.pitch = pitch.value;
  utterThis.rate = rate.value;
  synth.speak(utterThis);

  utterThis.onpause = (event) => {
    const char = event.utterance.text.charAt(event.charIndex);
    console.log(
      `Speech paused at character ${event.charIndex} of "${event.utterance.text}", which is "${char}".`,
    );
  };

  inputTxt.blur();
};
```

Specifications
--------------

| Specification |
| --- |
| Web Speech API # speechsynthesisvoice |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Web Speech API


HTMLCollection - Web APIs

HTMLCollection
==============

The **`HTMLCollection`** interface represents a generic collection (array-like object similar to `arguments`) of elements (in document order) and offers methods and properties for selecting from the list.

**Note:** This interface is called `HTMLCollection` for historical reasons (before the modern DOM, collections implementing this interface could only have HTML elements as their items).

An `HTMLCollection` in the HTML DOM is live; it is automatically updated when the underlying document is changed. For this reason it is a good idea to make a copy (e.g., using `Array.from`) to iterate over if adding, moving, or removing nodes.

**Note:** This interface was an attempt to create an unmodifiable list and only continues to be supported to not break code that's already using it. Modern APIs use types that wrap around ECMAScript array types instead, so you can treat them like ECMAScript arrays, and at the same time impose additional semantics on their usage (such as making their items read-only).

Instance properties
-------------------

`HTMLCollection.length` Read only

Returns the number of items in the collection.

Instance methods
----------------

`HTMLCollection.item()`

Returns the specific element at the given zero-based `index` into the list. Returns `null` if the `index` is out of range.

An alternative to accessing `collection[i]` (which instead returns `undefined` when `i` is out-of-bounds). This is mostly useful for non-JavaScript DOM implementations.

`HTMLCollection.namedItem()`

Returns the specific node whose ID or, as a fallback, name matches the string specified by `name`. Matching by name is only done as a last resort, only in HTML, and only if the referenced element supports the `name` attribute. Returns `null` if no node exists by the given name.

An alternative to accessing `collection[name]` (which instead returns `undefined` when `name` does not exist). This is mostly useful for non-JavaScript DOM implementations.

Usage in JavaScript
-------------------

`HTMLCollection` also exposes its members as properties by name and index. HTML IDs may contain `:` and `.` as valid characters, which would necessitate using bracket notation for property access. Currently, an `HTMLCollection` object does not recognize purely numeric IDs, which would cause conflict with the array-style access, though HTML does permit these.

For example, assuming there is one `<form>` element in the document and its `id` is `myForm`:

```js
let elem1, elem2;

// document.forms is an HTMLCollection

elem1 = document.forms[0];
elem2 = document.forms.item(0);

alert(elem1 === elem2); // shows: "true"

elem1 = document.forms.myForm;
elem2 = document.forms.namedItem("myForm");

alert(elem1 === elem2); // shows: "true"

elem1 = document.forms["named.item.with.periods"];
```

Specifications
--------------

| Specification |
| --- |
| DOM Standard # interface-htmlcollection |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `NodeList`
* `HTMLFormControlsCollection`, `HTMLOptionsCollection`


SVGFEDisplacementMapElement - Web APIs

SVGFEDisplacementMapElement
===========================

The **`SVGFEDisplacementMapElement`** interface corresponds to the `<feDisplacementMap>` element.

EventTarget

Node

Element

SVGElement

SVGFEDisplacementMapElementConstants
---------

| Name | Value | Description |
| --- | --- | --- |
| `SVG_CHANNEL_UNKNOWN` | 0 |
 The type is not one of predefined types. It is invalid to attempt to
 define a new value of this type or to attempt to switch an existing
 value to this type.
  |
| `SVG_CHANNEL_R` | 1 | Corresponds to the `R` value. |
| `SVG_CHANNEL_G` | 2 | Corresponds to the `G` value. |
| `SVG_CHANNEL_B` | 3 | Corresponds to the `B` value. |
| `SVG_CHANNEL_A` | 4 | Corresponds to the `A` value. |

Instance properties
-------------------

*This interface also inherits properties from its parent interface, `SVGElement`.*

`SVGFEDisplacementMapElement.height` Read only

An `SVGAnimatedLength` corresponding to the `height` attribute of the given element.

`SVGFEDisplacementMapElement.in1` Read only

An `SVGAnimatedString` corresponding to the `in` attribute of the given element.

`SVGFEDisplacementMapElement.in2` Read only

An `SVGAnimatedString` corresponding to the `in2` attribute of the given element.

`SVGFEDisplacementMapElement.result` Read only

An `SVGAnimatedString` corresponding to the `result` attribute of the given element.

`SVGFEDisplacementMapElement.scale` Read only

An `SVGAnimatedNumber` corresponding to the `scale` attribute of the given element.

`SVGFEDisplacementMapElement.width` Read only

An `SVGAnimatedLength` corresponding to the `width` attribute of the given element.

`SVGFEDisplacementMapElement.x` Read only

An `SVGAnimatedLength` corresponding to the `x` attribute of the given element.

`SVGFEDisplacementMapElement.xChannelSelector` Read only

An `SVGAnimatedEnumeration` corresponding to the `xChannelSelect` attribute of the given element. It takes one of the `SVG_CHANNEL_*` constants defined on this interface.

`SVGFEDisplacementMapElement.y` Read only

An `SVGAnimatedLength` corresponding to the `y` attribute of the given element.

`SVGFEDisplacementMapElement.yChannelSelector` Read only

An `SVGAnimatedEnumeration` corresponding to the `yChannelSelect` attribute of the given element. It takes one of the `SVG_CHANNEL_*` constants defined on this interface.

Instance methods
----------------

*This interface does not provide any specific methods, but implements those of its parent, `SVGElement`.*

Specifications
--------------

| Specification |
| --- |
| Filter Effects Module Level 1 # InterfaceSVGFEDisplacementMapElement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `<feDisplacementMap>`


InkPresenter - Web APIs

InkPresenter
============

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`InkPresenter`** interface of the Ink API provides the ability to instruct the OS-level compositor to render ink strokes between pointer event dispatches.

Instance properties
-------------------

`expectedImprovement`
Experimental
 Read only

Returns a value, in milliseconds, indicating the latency improvement that can be expected using this presenter.

`presentationArea`
Experimental
 Read only

Returns the `Element` inside which rendering of ink strokes is confined.

Instance methods
----------------

`updateInkTrailStartPoint()`
Experimental

Passes the `PointerEvent` that was used as the last rendering point for the current frame, allowing the OS-level compositor to render a delegated ink trail ahead of the next pointer event being dispatched.

Example
-------

In this example, we draw a trail onto a 2D canvas. Near the start of the code, we call `Ink.requestPresenter()`, passing it the canvas as the presentation area for it to take care of and storing the promise it returns in the `presenter` variable.

Later on, in the `pointermove` event listener, the new position of the trailhead is drawn onto the canvas each time the event fires. In addition, the `InkPresenter` object returned when the `presenter` promise fulfills has its `updateInkTrailStartPoint()` method invoked; this is passed:

* The last trusted pointer event representing the rendering point for the current frame.
* A `style` object containing color and diameter settings.

The result is that a delegated ink trail is drawn ahead of the default browser rendering on the app's behalf, in the specified style, until the next time it receives a `pointermove` event.

```js
const ctx = canvas.getContext("2d");
let presenter = navigator.ink.requestPresenter({ presentationArea: canvas });
let move_cnt = 0;
let style = { color: "rgb(0 0 255 / 100%)", diameter: 10 };

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() \* (max - min + 1)) + min;
}

canvas.addEventListener("pointermove", (evt) => {
  const pointSize = 10;
  ctx.fillStyle = "#000000";
  ctx.fillRect(evt.pageX, evt.pageY, pointSize, pointSize);
  if (move_cnt == 50) {
    let r = getRandomInt(0, 255);
    let g = getRandomInt(0, 255);
    let b = getRandomInt(0, 255);
    style = {
      color: "rgb(" + r + " " + g + " " + b + " / 100%)",
      diameter: 10,
    };
    move_cnt = 0;
    document.getElementById("div").style.backgroundColor =
      "rgb(" + r + " " + g + " " + b + " / 100%)";
  }
  move_cnt += 1;
  presenter.then(function (v) {
    v.updateInkTrailStartPoint(evt, style);
  });
});

window.addEventListener("pointerdown", (evt) => {
  evt.pointerId;
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
});

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
```

**Note:** See this example running live — Delegated ink trail.

Specifications
--------------

| Specification |
| --- |
| Ink API # ink-presenter |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Enhancing Inking on the Web


Ink API - Web APIs

Ink API
=======

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The Ink API allows browsers to directly make use of available OS-level compositors when drawing pen strokes in an inking app feature, thereby reducing latency and increasing performance.

Concepts and usage
------------------

Inking on the web refers to app features that involve using pointer events to draw a smooth pen stroke — for example, a drawing app or document signing feature.

Pointers events are usually sent first to the browser process, which then forwards these events to the JavaScript event loop to execute the associated handler functions and render the result in the app. The time delay between the start and finish of this process can be significant, resulting in latency between the user initiating drawing (for example, with a stylus or mouse), and the stroke showing up on the screen.

The Ink API significantly reduces this latency by allowing browsers to bypass the JavaScript event loop entirely. Where possible, browsers will pass such rendering instructions directly to OS-level compositors. If the underlying operating system does not have a specialized OS-level compositor to use for this purpose, browsers will use their own optimized rendering code. This is not as powerful as a compositor, but it still confers some improvements.

**Note:** Compositors are part of the rendering machinery that draws the UI to the screen in a browser or operating system. See Inside look at modern web browser (part 3) for some interesting insights into how a compositor functions inside a web browser.

The entry point is the `Navigator.ink` property, which returns an `Ink` object for the current document. The `Ink.requestPresenter()` method returns a `Promise` that fulfills with an `InkPresenter` object instance. This instructs the OS-level compositor to render ink strokes between pointer event dispatches in the next available frame in each case.

Interfaces
----------

`Ink`

Provides access to `InkPresenter` objects for the application to use to render the strokes.

`InkPresenter`

Instructs the OS-level compositor to render ink strokes between pointer event dispatches.

### Extensions to other interfaces

`Navigator.ink` Read only
Experimental

Returns an `Ink` object for the current document.

Examples
--------

### Drawing an ink trail

In this example, we draw a trail onto a 2D canvas. Near the start of the code, we call `Ink.requestPresenter()`, passing it the canvas as the presentation area for it to take care of and storing the promise it returns in the `presenter` variable.

Later on, in the `pointermove` event listener, the new position of the trailhead is drawn onto the canvas each time the event fires. In addition, the `InkPresenter` object returned when the `presenter` promise fulfills has its `updateInkTrailStartPoint()` method invoked; this is passed:

* The last trusted pointer event representing the rendering point for the current frame.
* A `style` object containing color and diameter settings.

The result is that a delegated ink trail is drawn ahead of the default browser rendering on the app's behalf, in the specified style, until the next time it receives a `pointermove` event.

#### HTML

```html
<canvas id="canvas"></canvas>
<div id="div">Delegated ink trail should match the color of this div.</div>
```

#### CSS

```css
div {
  background-color: rgb(0 255 0 / 100%);
  position: fixed;
  top: 1rem;
  left: 1rem;
}
```

#### JavaScript

```js
const ctx = canvas.getContext("2d");
const presenter = navigator.ink.requestPresenter({ presentationArea: canvas });
let move_cnt = 0;
let style = { color: "rgb(0 255 0 / 100%)", diameter: 10 };

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() \* (max - min + 1)) + min;
}

canvas.addEventListener("pointermove", async (evt) => {
  const pointSize = 10;
  ctx.fillStyle = style.color;
  ctx.fillRect(evt.pageX, evt.pageY, pointSize, pointSize);
  if (move_cnt == 20) {
    const r = getRandomInt(0, 255);
    const g = getRandomInt(0, 255);
    const b = getRandomInt(0, 255);

    style = { color: `rgb(${r} ${g} ${b} / 100%)`, diameter: 10 };
    move_cnt = 0;
    document.getElementById("div").style.backgroundColor =
      `rgb(${r} ${g} ${b} / 60%)`;
  }
  move_cnt += 1;
  await presenter.updateInkTrailStartPoint(evt, style);
});

window.addEventListener("pointerdown", () => {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
});

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
```

#### Result

Specifications
--------------

| Specification |
| --- |
| Ink API # ink-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Enhancing Inking on the Web


RTCEncodedVideoFrame - Web APIs

RTCEncodedVideoFrame
====================

The **`RTCEncodedVideoFrame`** of the WebRTC API represents an encoded video frame in the WebRTC receiver or sender pipeline, which may be modified using a WebRTC Encoded Transform.

**Note:** This feature is available in *Dedicated* Web Workers.

Instance properties
-------------------

`RTCEncodedVideoFrame.type` Read only

Returns whether the current frame is a key frame, delta frame, or empty frame.

`RTCEncodedVideoFrame.timestamp` Read only

Returns the timestamp at which sampling of the frame started.

`RTCEncodedVideoFrame.data`

Return a buffer containing the encoded frame data.

Instance methods
----------------

`RTCEncodedVideoFrame.getMetadata()`

Returns the metadata associated with the frame.

Description
-----------

 Raw video data is generated as a sequence of frames, where each frame is a 2 dimensional array of pixel values.
 Video encoders transform this raw input into a compressed representation of the original for transmission and storage.
 A common approach is to send "key frames" that contain enough information to reproduce a whole image at a relatively low rate, and between key frames to send many much smaller "delta frames" that just encode the changes since the previous frame.

There are many different codecs, such as H.264, VP8, and VP9, each that have a different encoding processes and configuration, which offer different trade-offs between compression efficiency and video quality.

 The **`RTCEncodedVideoFrame`** represents a single frame encoded with a particular video encoder.
 The `type` property indicates whether the frame is a "key" or "delta" frame, and you can use the `getMetadata()` method to get other details about the encoding method.
 The `data` property provides access to the encoded image data for the frame, which can then be modified ("transformed") when frames are sent or received.

Examples
--------

This code snippet shows a handler for the `rtctransform` event in a `Worker` that implements a `TransformStream`, and pipes encoded frames through it from the `event.transformer.readable` to `event.transformer.writable` (`event.transformer` is a `RTCRtpScriptTransformer`, the worker-side counterpart of `RTCRtpScriptTransform`).

 If the tranformer is inserted into a video stream, the `transform()` method is called with a `RTCEncodedVideoFrame` whenever a new frame is enqueued on `event.transformer.readable`.
 The `transform()` method shows how this might be read, modified by inverting the bits, and then enqueued on the controller (this ultimately pipes it through to the `event.transformer.writable`, and then back into the WebRTC pipline).

```js
addEventListener("rtctransform", (event) => {
  const async transform = new TransformStream({
    async transform(encodedFrame, controller) {
      // Reconstruct the original frame.
      const view = new DataView(encodedFrame.data);

      // Construct a new buffer
      const newData = new ArrayBuffer(encodedFrame.data.byteLength);
      const newView = new DataView(newData);

      // Negate all bits in the incoming frame
      for (let i = 0; i < encodedFrame.data.byteLength; ++i) {
        newView.setInt8(i, ~view.getInt8(i));
      }

      encodedFrame.data = newData;
      controller.enqueue(encodedFrame);
    },
  });
  event.transformer.readable
    .pipeThrough(transform)
    .pipeTo(event.transformer.writable);
});
```

Note that more complete examples are provided in Using WebRTC Encoded Transforms.

Specifications
--------------

| Specification |
| --- |
| WebRTC Encoded Transform # rtcencodedvideoframe |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using WebRTC Encoded Transforms
* `TransformStream`
* `RTCRtpScriptTransformer`
* `RTCEncodedAudioFrame`


SVGImageElement - Web APIs

SVGImageElement
===============

The **`SVGImageElement`** interface corresponds to the `<image>` element.

EventTarget

Node

Element

SVGElement

SVGGraphicsElement

SVGImageElementInstance properties
-------------------

*This interface also inherits properties from its parent, `SVGGraphicsElement`.*

`SVGImageElement.href` Read only

An `SVGAnimatedString` corresponding to the `href` or `xlink:href`
Deprecated
 attribute of the given `<image>` element.

`SVGImageElement.decoding`

Represents a hint given to the browser on how it should decode the image. If this value is provided, it must be one of the possible permitted values: `"sync"` to decode the image synchronously, `"async"` to decode it asynchronously, or `"auto"` to indicate no preference (which is the default).

`SVGImageElement.height` Read only

An `SVGAnimatedLength` corresponding to the `height` attribute of the given `<image>` element.

`SVGImageElement.preserveAspectRatio` Read only

An `SVGAnimatedPreserveAspectRatio` corresponding to the `preserveAspectRatio` attribute of the given `<image>` element.

`SVGImageElement.width` Read only

An `SVGAnimatedLength` corresponding to the `width` attribute of the given `<image>` element.

`SVGImageElement.x` Read only

An `SVGAnimatedLength` corresponding to the `x` attribute of the given `<image>` element.

`SVGImageElement.y` Read only

An `SVGAnimatedLength` corresponding to the `y` attribute of the given `<image>` element.

Instance methods
----------------

*This interface also inherits methods from its parent interface, `SVGGraphicsElement`.*

`SVGImageElement.decode()`

Initiates asynchronous decoding of the image data. Returns a `Promise` which resolves once the image data is ready to be used.

Specifications
--------------

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 2 # InterfaceSVGImageElement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLHeadElement - Web APIs

HTMLHeadElement
===============

The **`HTMLHeadElement`** interface contains the descriptive information, or metadata, for a document. This object inherits all of the properties and methods described in the `HTMLElement` interface.

EventTarget

Node

Element

HTMLElement

HTMLHeadElementInstance properties
-------------------

*Inherits properties from its parent, `HTMLElement`.*

`HTMLHeadElement.profile`
Deprecated

A string representing the URIs of one or more metadata profiles (white space separated).

Instance methods
----------------

*No specific method; inherits methods from its parent, `HTMLElement`.*

Specifications
--------------

| Specification |
| --- |
| HTML Standard # htmlheadelement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The HTML element implementing this interface: `<head>`


Shared Storage API - Web APIs

Shared Storage API
==================

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **Shared Storage API** is a client-side storage mechanism that enables unpartitioned, cross-site data access while preserving privacy (i.e. without relying on tracking cookies).

Concepts and usage
------------------

One major source of privacy and security problems on the web is the use of cookies set on third-party content embedded in sites (for example via `<iframe>` elements). These cookies can be used to track and profile users, and share information across sites.

To prevent cross-site tracking, browsers are working towards partitioning all storage types, including Cookies, Web Storage, IndexedDB, and the Cache API. However, a major barrier to achieving this is the need for several legitimate use cases that rely on cross-site information sharing. Examples of such use cases include advertisers wanting to measure the reach of their ads across sites and generate reports, and site owners wanting to customize user experiences based on the group they are in or their previous site interactions.

The Shared Storage API provides a flexible solution for such use cases. It aims to provide the required data storage, processing, and sharing capabilities without the ability to track and profile users.

Like other storage APIs, you can write to shared storage at any time. However, you can only read shared storage data from inside a worklet. Worklets provide a secure environment inside which you can process shared storage data and return useful results, but you can't directly share the data with the associated browsing context.

To extract useful results from a shared storage worklet, you need to use an **output gate**. These gates serve specific purposes such as selecting a URL from a provided list to display to the user based on shared storage data. Results meant for the user are shown securely inside a fenced frame where they can't be accessed from the embedding page.

Output gates
------------

The currently available output gates for the Shared Storage API are discussed in the sections below. In each section, we list typical use cases for each gate and provide links to guides with more information and code examples.

**Note:** More output gates will likely be added in the future to support additional use cases.

### URL Selection

The **URL Selection** output gate, accessed via the `selectURL()` method, is used to select a URL from a provided list to display to the user, based on shared storage data. This gate be used for the following purposes:

* **Creative rotation**: Use stored data such as creative IDs, view counts, and user interaction to determine which creative content users see across different sites. This approach helps in balancing views and prevents overexposure of certain content, which in turn can help avoid a negative user experience.
* **A/B testing**: Assign a user to an experiment group, then store group details in shared storage for cross-site access.
* **Custom user experiences**: Share custom content and calls-to-action based on a user's registration status or other user states.
### Run

The **Run** output gate, accessed via the `run()` method, is intended to be used in a generic way to process some shared storage data.

The Private Aggregation API can use the Run output gate to process shared storage data and generate aggregated reports. These reports can be used in the following use cases:

* **Unique reach reporting**: Content producers and advertisers often want to know the number of unique viewers for their content. You can use shared storage to report the first time a user sees your ad or embedded publication and prevent duplicate counting for the same user on a different site, giving you an aggregated noisy report of approximate unique reach.
* **User demographic reporting**: Content producers often want to understand the demographics of their audience. You can use shared storage to record user demographic data on your main site, and use aggregated reporting to report on it across other sites in embedded contexts.
* **K+ frequency measurement**: Sometimes described as "effective frequency", K+ frequency refers to the minimum number of views needed before a user will recognize or recall certain content (often used in the context of ad views). You can use shared storage to build reports of unique users who have seen a piece of content at least K times.
Understanding how shared storage works
--------------------------------------

There are two parts to using the Shared Storage API — writing data to storage and reading/processing it. To give you an idea of how these parts are handled, we'll walk you through the basic A/B testing example from developer.chrome.com. In this example, a user is assigned to an experiment group, and the group details are stored in shared storage. Other sites are able to use this data when choosing a URL to display in a fenced frame.

### Writing to shared storage

Writing data to shared storage is simple — you use methods defined on the `SharedStorage` interface to set, append, or delete/clear data.

This functionality is available in two different contexts:

* In the main browsing context, where your site or app runs, on `WindowSharedStorage`. This is available via `window.sharedStorage`.
* In the context of your shared storage worklet, on `WorkletSharedStorage`. This is available via `this.sharedStorage`.

In our A/B testing example, we define a function in our app context that generates a random number — 0 or 1 — to represent an experiment group. We then run the `window.sharedStorage.set()` function to assign the user to a group and save the result in shared storage:

```js
// Randomly assigns a user to a group 0 or 1
function getExperimentGroup() {
  return Math.round(Math.random());
}

async function injectContent() {
  // Assign user to a random group (0 or 1) and store it in shared storage
  window.sharedStorage.set("ab-testing-group", getExperimentGroup(), {
    ignoreIfPresent: true,
  });
}
```

**Note:** The `ignoreIfPresent: true` option causes the `set()` function to abort if the shared storage already contains a data item with the specified key.

### Reading and processing data from shared storage

As mentioned above, to extract useful results from a shared storage worklet, you need to use an **output gate**. In this example, we'll use the URL Selection output gate to read the user's experiment group and then display a URL in a fenced frame based on their group.

To use the output gate, you need to:

1. Define an operation in a worklet module script to handle choosing the URL, and register it.
2. Add the module to your shared storage worklet.
3. Choose the URL using the worklet operation and load it in a fenced frame.

Below we'll look at these steps one by one.

#### Define an operation in a worklet module

The URL selection is based on the experiment group stored in shared storage. To retrieve this value and choose a URL based on it, we need to define an operation in a `SharedStorageWorklet` context. This ensures the raw data is hidden from other contexts, thereby preserving privacy.

The URL Selection operation is a JavaScript class that must follow the rules below (these rules vary for each output gate, depending on their intended use case):

* The actual functionality must be contained in an asynchronous `run()` method, which takes an array of objects containing URLs as its first parameter and a data object as its second parameter (when called, the data argument is optional).
* The `run()` method must return a number, which will equate to the number of the URL chosen.

**Note:** Each output gate has a corresponding interface that defines the required structure of its class and `run()` method. For URL Selection, see `SharedStorageSelectURLOperation`.

Once the operation is defined, it needs to be registered using `SharedStorageWorkletGlobalScope.register()`.

```js
// ab-testing-worklet.js
class SelectURLOperation {
  async run(urls, data) {
    // Read the user's experiment group from shared storage
    const experimentGroup = await this.sharedStorage.get("ab-testing-group");

    // Return the group number
    return experimentGroup;
  }
}

register("ab-testing", SelectURLOperation);
```

Notice how the value set in our main app context is retrieved using `WorkletSharedStorage.get()`. To reiterate, to preserve privacy and mitigate data leakage, you can read values from shared storage only within a worklet.

**Note:** It is possible to define and register multiple operations in the same shared storage worklet module script with different names; see `SharedStorageOperation` for an example.

#### Add the module to the shared storage worklet

To use the operation defined in the worklet module, it needs to be added to the shared storage worklet using `window.sharedStorage.worklet.addModule()`. In our main app context, this is done before we set the experiment group value, so that it is ready to use when needed:

```js
async function injectContent() {
  // Add the module to the shared storage worklet
  await window.sharedStorage.worklet.addModule("ab-testing-worklet.js");

  // Assign user to a random group (0 or 1) and store it in shared storage
  window.sharedStorage.set("ab-testing-group", getExperimentGroup(), {
    ignoreIfPresent: true,
  });
}
```

#### Choose a URL and load it in a fenced frame

To run the operation defined in the worklet, we call `WindowSharedStorage.selectURL()`. This method acts as a proxy to our worklet operation, accessing it securely and returning the result without leaking any data. `selectURL()` is the correct method to call our user-defined worklet operation because it was defined with the appropriate class structure for a URL Selection operation, as discussed above.

`selectURL()` expects an array of objects containing URLs to choose from, an optional options object, and for the underlying operation to return an integer that it can use to choose a URL.

```js
// Run the URL selection operation
const fencedFrameConfig = await window.sharedStorage.selectURL(
  "ab-testing",
  [
    { url: `https://your-server.example/content/default-content.html` },
    { url: `https://your-server.example/content/experiment-content-a.html` },
  ],
  {
    resolveToConfig: true,
  },
);
```

Because the options object contains `resolveToConfig: true`, the returned `Promise` will resolve with a `FencedFrameConfig` object. This object can be set as the value of the `HTMLFencedFrameElement.config` property, resulting in the content of the chosen URL being displayed in the corresponding `<fencedframe>` element:

```js
document.getElementById("content-slot").config = fencedFrameConfig;
```

The full app script looks like so:

```js
// Randomly assigns a user to a group 0 or 1
function getExperimentGroup() {
  return Math.round(Math.random());
}

async function injectContent() {
  // Add the module to the shared storage worklet
  await window.sharedStorage.worklet.addModule("ab-testing-worklet.js");

  // Assign user to a random group (0 or 1) and store it in shared storage
  window.sharedStorage.set("ab-testing-group", getExperimentGroup(), {
    ignoreIfPresent: true,
  });

  // Run the URL selection operation
  const fencedFrameConfig = await window.sharedStorage.selectURL(
    "ab-testing",
    [
      { url: `https://your-server.example/content/default-content.html` },
      { url: `https://your-server.example/content/experiment-content-a.html` },
    ],
    {
      resolveToConfig: true,
    },
  );

  // Render the chosen URL into a fenced frame
  document.getElementById("content-slot").config = fencedFrameConfig;
}

injectContent();
```

Differences between shared storage and web storage
--------------------------------------------------

The key difference is that shared storage is intended for use with cross-origin data after storage has been partitioned.

* If you are a publisher and you want to store first-party data that is accessible to only you, use the `localStorage` version of web storage.
* If you want data to persist only during a browser session, use `sessionStorage`.
* If you are operating as a third-party on another site, and you want to record data from that site to access later on another site, use shared storage.

Another important difference between shared storage and web storage is that reading from shared storage is guarded (writing to storage behaves similarly). With `localStorage` and `sessionStorage`, you can read freely. With shared storage, reading can happen only within a shared storage worklet, and the origin used for reading in the worklet is the same as the browsing context that created it.

Additionally, you cannot extract shared storage data outside of a shared storage worklet, as a tracking protection. You must use one of the output gates to work with your data in shared storage.

Lastly, data in `localStorage` persists until it is manually cleared. `sessionStorage` clears at the end of a browsing session, whereas shared storage data clears 30 days after the last write call.

Interfaces
----------

`SharedStorage`

Represents the shared storage for a particular origin. It defines methods to write data to the shared storage.

`WindowSharedStorage`

Represents the shared storage for a particular origin as exposed to a standard browsing context. Among other things, it defines methods to use the available output gates, which act as proxies for the operations defined in the worklet.

`WorkletSharedStorage`

Represents the shared storage for a particular origin within a worklet context. Among other things, it defines methods to read the shared storage data.

`SharedStorageWorklet`

Represents the current origin's shared storage worklet. It contains the `addModule()` method for adding modules. Unlike a regular `Worklet`, the `SharedStorageWorklet` can have only a single module added to it, for privacy reasons.

`SharedStorageWorkletGlobalScope`

Represents the global scope of a `SharedStorageWorklet` module. It contains the functionality to register a defined operation and access the shared storage.

### Output gate operation signature definitions

`SharedStorageOperation`

Represents the base class for all different output gate operation types.

`SharedStorageRunOperation`

Represents a Run output gate operation.

`SharedStorageSelectURLOperation`

Represents a URL Selection output gate operation.

### Extensions to other interfaces

`Window.sharedStorage`

Returns the `WindowSharedStorage` object for the current origin.

Enrollment and local testing
----------------------------

To use the Shared Storage API in your sites, you must specify it in the privacy sandbox enrollment process. If you don't, the Shared Storage API methods won't run successfully.

You can test your Shared Storage API code locally without enrollment. To allow local testing, enable the following Chrome developer flag:

`chrome://flags/#privacy-sandbox-enrollment-overrides`

Examples
--------

For extensive demos, see the Shared Storage API demo site, which also includes some Private Aggregation API examples.

Specifications
--------------

| Specification |
| --- |
| Shared Storage API # sharedstorage |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Shared Storage on developer.chrome.com
* The Privacy Sandbox on developer.chrome.com


CaretPosition - Web APIs

CaretPosition
=============

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The `CaretPosition` interface represents the caret position, an indicator for the text insertion point. You can get a `CaretPosition` using the `Document.caretPositionFromPoint()` method.

Instance properties
-------------------

*This interface doesn't inherit any properties.*

`CaretPosition.offsetNode` Read only
Experimental

Returns a `Node` containing the found node at the caret's position.

`CaretPosition.offset` Read only
Experimental

Returns a `long` representing the character offset in the caret position node.

Instance methods
----------------

`CaretPosition.getClientRect`
Experimental

Returns the client rectangle for the caret range.

Specifications
--------------

| Specification |
| --- |
| CSSOM View Module # caret-position |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Document.caretPositionFromPoint()`
* `Range`
* `Node`


HTMLScriptElement - Web APIs

HTMLScriptElement
=================

HTML `<script>` elements expose the **`HTMLScriptElement`** interface, which provides special properties and methods for manipulating the behavior and execution of `<script>` elements (beyond the inherited `HTMLElement` interface).

JavaScript files should be served with the `text/javascript` MIME type, but browsers are lenient and block them only if the script is served with an image type (`image/*`), video type (`video/*`), audio type (`audio/*`), or `text/csv`. If the script is blocked, its element receives an `error` event; otherwise, it receives a `load` event.

EventTarget

Node

Element

HTMLElement

HTMLScriptElementInstance properties
-------------------

*Inherits properties from its parent, `HTMLElement`.*

`HTMLScriptElement.type`

A string representing the MIME type of the script. It reflects the `type` attribute.

`HTMLScriptElement.src`

A string representing the URL of an external script. It reflects the `src` attribute.

`HTMLScriptElement.event`
Deprecated

A string; an obsolete way of registering event handlers on elements in an HTML document.

`HTMLScriptElement.charset`
Deprecated

A string representing the character encoding of an external script. It reflects the `charset` attribute.

`HTMLScriptElement.async`, `HTMLScriptElement.defer`

The `async` and `defer` attributes are boolean attributes that control how the script should be executed. **The `defer` and `async` attributes must not be specified if the `src` attribute is absent.**

There are three possible execution modes:

1. If the `async` attribute is present, then the script will be executed asynchronously as soon as it downloads.
2. If the `async` attribute is absent but the `defer` attribute is present, then the script is executed when the page has finished parsing.
3. If neither attribute is present, then the script is fetched and executed immediately, blocking further parsing of the page.

The `defer` attribute may be specified with the `async` attribute, so legacy browsers that only support `defer` (and not `async`) fall back to the `defer` behavior instead of the default blocking behavior.

**Note:** The exact processing details for these attributes are complex, involving many different aspects of HTML, and therefore are scattered throughout the specification. These algorithms describe the core ideas, but they rely on the parsing rules for `<script>` start and end tags in HTML, in foreign content, and in XML; the rules for the `document.write()` method; the handling of scripting; and so on.

`HTMLScriptElement.crossOrigin`

A string reflecting the CORS setting for the script element. For classic scripts from other origins, this controls if error information will be exposed.

`HTMLScriptElement.text`

A string that joins and returns the contents of all `Text` nodes inside the `<script>` element (ignoring other nodes like comments) in tree order. On setting, it acts the same way as the `textContent` IDL attribute.

**Note:** When inserted using the `document.write()` method, `<script>` elements execute (typically synchronously), but when inserted using `innerHTML` or `outerHTML`, they do not execute at all.

`HTMLScriptElement.fetchPriority`

An optional string representing a hint given to the browser on how it should prioritize fetching of an external script relative to other external scripts. If this value is provided, it must be one of the possible permitted values: `high` to fetch at a high priority, `low` to fetch at a low priority, or `auto` to indicate no preference (which is the default).

`HTMLScriptElement.noModule`

A boolean value that if true, stops the script's execution in browsers that support ES modules — used to run fallback scripts in older browsers that do *not* support JavaScript modules.

`HTMLScriptElement.referrerPolicy`

A string that reflects the `referrerPolicy` HTML attribute indicating which referrer to use when fetching the script, and fetches done by that script.

Static methods
--------------

`HTMLScriptElement.supports()`

 Returns `true` if the browser supports scripts of the specified type and `false` otherwise.
 This method provides a simple and unified method for script-related feature detection.

Instance methods
----------------

*No specific methods; inherits methods from its parent, `HTMLElement`.*

Events
------

*No specific events; inherits events from its parent, `HTMLElement`.*

Examples
--------

### Dynamically importing scripts

 Let's create a function that imports new scripts within a document creating a `<script>` node *immediately before* the `<script>` that hosts the following code (through `document.currentScript`).
 These scripts will be **asynchronously** executed.
 For more details, see the `defer` and `async` properties.

```js
function loadError(oError) {
  throw new URIError(`The script ${oError.target.src} didn't load correctly.`);
}

function prefixScript(url, onloadFunction) {
  const newScript = document.createElement("script");
  newScript.onerror = loadError;
  if (onloadFunction) {
    newScript.onload = onloadFunction;
  }
  document.currentScript.parentNode.insertBefore(
    newScript,
    document.currentScript,
  );
  newScript.src = url;
}
```

This next function, instead of prepending the new scripts immediately before the `document.currentScript` element, appends them as children of the `<head>` tag.

```js
function loadError(oError) {
  throw new URIError(`The script ${oError.target.src} didn't load correctly.`);
}

function affixScriptToHead(url, onloadFunction) {
  const newScript = document.createElement("script");
  newScript.onerror = loadError;
  if (onloadFunction) {
    newScript.onload = onloadFunction;
  }
  document.head.appendChild(newScript);
  newScript.src = url;
}
```

Sample usage:

```js
affixScriptToHead("myScript1.js");
affixScriptToHead("myScript2.js", () => {
  alert('The script "myScript2.js" has been correctly loaded.');
});
```

### Checking if a script type is supported

`HTMLScriptElement.supports()` provides a unified mechanism for checking whether a browser supports particular types of scripts.

The example below shows how to check for module support, using the existence of the `noModule` attribute as a fallback.

```js
function checkModuleSupport() {
  if ("supports" in HTMLScriptElement) {
    return HTMLScriptElement.supports("module");
  }
  return "noModule" in document.createElement("script");
}
```

Classic scripts are assumed to be supported on all browsers.

Specifications
--------------

| Specification |
| --- |
| HTML Standard # htmlscriptelement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* HTML `<script>` element
* HTML `<noscript>` element
* `document.currentScript`
* Web Workers (code snippets similar to scripts but executed in another global context)


GPUExternalTexture - Web APIs

GPUExternalTexture
==================

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **`GPUExternalTexture`** interface of the WebGPU API represents a wrapper object containing an `HTMLVideoElement` snapshot that can be used as a texture in GPU rendering operations.

A `GPUExternalTexture` object instance is created using `GPUDevice.importExternalTexture()`.

Instance properties
-------------------

`label`
Experimental

A string providing a label that can be used to identify the object, for example in `GPUError` messages or console warnings.

Examples
--------

In the WebGPU samples Video Uploading sample, a `GPUExternalTexture` object (created via a `GPUDevice.importExternalTexture()` call) is used as the value of a bind group entry `resource`, specified when creating a `GPUBindGroup` via a `GPUDevice.createBindGroup()` call:

```js
//...
const uniformBindGroup = device.createBindGroup({
  layout: pipeline.getBindGroupLayout(0),
  entries: [
    {
      binding: 1,
      resource: sampler,
    },
    {
      binding: 2,
      resource: device.importExternalTexture({
        source: video,
      }),
    },
  ],
});
//...
```

Specifications
--------------

| Specification |
| --- |
| WebGPU # gpuexternaltexture |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The WebGPU API


IDBIndex - Web APIs

IDBIndex
========

`IDBIndex` interface of the IndexedDB API provides asynchronous access to an index in a database. An index is a kind of object store for looking up records in another object store, called the referenced object store. You use this interface to retrieve data.

You can retrieve records in an object store through the primary key or by using an index. An index lets you look up records in an object store using properties of the values in the object stores records other than the primary key

The index is a persistent key-value storage where the value part of its records is the key part of a record in the referenced object store. The records in an index are automatically populated whenever records in the referenced object store are inserted, updated, or deleted. Each record in an index can point to only one record in its referenced object store, but several indexes can reference the same object store. When the object store changes, all indexes that refers to the object store are automatically updated.

You can grab a set of keys within a range. To learn more, see `IDBKeyRange`.

**Note:** This feature is available in Web Workers

Instance properties
-------------------

`IDBIndex.isAutoLocale` Read only
Non-standard

Experimental

Returns a boolean value indicating whether the index had a `locale` value of `auto` specified upon its creation (see the `options` parameter to `IDBObjectStore.createIndex()`.)

`IDBIndex.locale` Read only
Non-standard

Experimental

Returns the locale of the index (for example `en-US`, or `pl`) if it had a `locale` value specified upon its creation (see the `options` parameter to `IDBObjectStore.createIndex()`.)

`IDBIndex.name`

The name of this index.

`IDBIndex.objectStore` Read only

The name of the object store referenced by this index.

`IDBIndex.keyPath` Read only

The key path of this index. If null, this index is not auto-populated.

`IDBIndex.multiEntry` Read only

Affects how the index behaves when the result of evaluating the index's key path yields an array. If `true`, there is one record in the index for each item in an array of keys. If `false`, then there is one record for each key that is an array.

`IDBIndex.unique` Read only

If `true`, this index does not allow duplicate values for a key.

Instance methods
----------------

Inherits from: EventTarget

`IDBIndex.count()`

Returns an `IDBRequest` object, and in a separate thread, returns the number of records within a key range.

`IDBIndex.get()`

Returns an `IDBRequest` object, and, in a separate thread, finds either the value in the referenced object store that corresponds to the given key or the first corresponding value, if `key` is an `IDBKeyRange`.

`IDBIndex.getKey()`

Returns an `IDBRequest` object, and, in a separate thread, finds either the given key or the primary key, if `key` is an `IDBKeyRange`.

`IDBIndex.getAll()`

Returns an `IDBRequest` object, in a separate thread, finds all matching values in the referenced object store that correspond to the given key or are in range, if `key` is an `IDBKeyRange`.

`IDBIndex.getAllKeys()`

Returns an `IDBRequest` object, in a separate thread, finds all matching keys in the referenced object store that correspond to the given key or are in range, if `key` is an `IDBKeyRange`.

`IDBIndex.openCursor()`

Returns an `IDBRequest` object, and, in a separate thread, creates a cursor over the specified key range.

`IDBIndex.openKeyCursor()`

Returns an `IDBRequest` object, and, in a separate thread, creates a cursor over the specified key range, as arranged by this index.

Example
-------

In the following example we open a transaction and an object store, then get the index `lName` from a simple contacts database. We then open a basic cursor on the index using `IDBIndex.openCursor` — this works the same as opening a cursor directly on an `ObjectStore` using `IDBObjectStore.openCursor` except that the returned records are sorted based on the index, not the primary key.

Finally, we iterate through each record, and insert the data into an HTML table. For a complete working example, see our IndexedDB-examples demo repo (View the example live.)

```js
function displayDataByIndex() {
  tableEntry.innerHTML = "";
  const transaction = db.transaction(["contactsList"], "readonly");
  const objectStore = transaction.objectStore("contactsList");

  const myIndex = objectStore.index("lName");
  myIndex.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      const tableRow = document.createElement("tr");
      tableRow.innerHTML =
        `<td>${cursor.value.id}</td>` +
        `<td>${cursor.value.lName}</td>` +
        `<td>${cursor.value.fName}</td>` +
        `<td>${cursor.value.jTitle}</td>` +
        `<td>${cursor.value.company}</td>` +
        `<td>${cursor.value.eMail}</td>` +
        `<td>${cursor.value.phone}</td>` +
        `<td>${cursor.value.age}</td>`;
      tableEntry.appendChild(tableRow);

      cursor.continue();
    } else {
      console.log("Entries all displayed.");
    }
  };
}
```

Specifications
--------------

| Specification |
| --- |
| Indexed Database API 3.0 # index-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Using IndexedDB
* Starting transactions: `IDBDatabase`
* Using transactions: `IDBTransaction`
* Setting a range of keys: `IDBKeyRange`
* Retrieving and making changes to your data: `IDBObjectStore`
* Using cursors: `IDBCursor`
* Reference example: To-do Notifications (View the example live).


TextDecoder - Web APIs

TextDecoder
===========

The **`TextDecoder`** interface represents a decoder for a specific text encoding, such as `UTF-8`, `ISO-8859-2`, `KOI8-R`, `GBK`, etc. A decoder takes a stream of bytes as input and emits a stream of code points.

**Note:** This feature is available in Web Workers

Constructor
-----------

`TextDecoder()`

Returns a newly constructed `TextDecoder` that will generate a code point stream with the decoding method specified in parameters.

Instance properties
-------------------

*The `TextDecoder` interface doesn't inherit any properties.*

`TextDecoder.encoding` Read only

A string containing the name of the decoder, which is a string describing the method the `TextDecoder` will use.

`TextDecoder.fatal` Read only

A `Boolean` indicating whether the error mode is fatal.

`TextDecoder.ignoreBOM` Read only

A `Boolean` indicating whether the byte order mark is ignored.

Instance methods
----------------

*The `TextDecoder` interface doesn't inherit any methods*.

`TextDecoder.decode()`

Returns a string containing the text decoded with the method of the specific `TextDecoder` object.

Examples
--------

### Representing text with typed arrays

This example shows how to decode a Chinese/Japanese character
 ![Chinese character meaning lucky](/en-US/docs/Web/API/TextDecoder/2019-05-21_191907.png), as represented by five different typed arrays: `Uint8Array`, `Int8Array`, `Uint16Array`, `Int16Array`, and `Int32Array`.

```js
let utf8decoder = new TextDecoder(); // default 'utf-8' or 'utf8'

let u8arr = new Uint8Array([240, 160, 174, 183]);
let i8arr = new Int8Array([-16, -96, -82, -73]);
let u16arr = new Uint16Array([41200, 47022]);
let i16arr = new Int16Array([-24336, -18514]);
let i32arr = new Int32Array([-1213292304]);

console.log(utf8decoder.decode(u8arr));
console.log(utf8decoder.decode(i8arr));
console.log(utf8decoder.decode(u16arr));
console.log(utf8decoder.decode(i16arr));
console.log(utf8decoder.decode(i32arr));
```

### Handling non-UTF8 text

In this example, we decode the Russian text "Привет, мир!", which means "Hello, world." In our `TextDecoder()` constructor, we specify the Windows-1251 character encoding, which is appropriate for Cyrillic script.

```js
const win1251decoder = new TextDecoder("windows-1251");
const bytes = new Uint8Array([
  207, 240, 232, 226, 229, 242, 44, 32, 236, 232, 240, 33,
]);
console.log(win1251decoder.decode(bytes)); // Привет, мир!
```

Specifications
--------------

| Specification |
| --- |
| Encoding Standard # interface-textdecoder |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The `TextEncoder` interface describing the inverse operation.
* A shim allowing to use this interface in browsers that do not support it.
* Node.js supports global export from v11.0.0


HTMLOListElement - Web APIs

HTMLOListElement
================

The **`HTMLOListElement`** interface provides special properties (beyond those defined on the regular `HTMLElement` interface it also has available to it by inheritance) for manipulating ordered list elements.

EventTarget

Node

Element

HTMLElement

HTMLOListElementInstance properties
-------------------

*Inherits properties from its parent, `HTMLElement`.*

`HTMLOListElement.reversed`

A boolean value reflecting the `reversed` and defining if the numbering is descending, that is its value is `true`, or ascending (`false`).

`HTMLOListElement.start`

A `long` value reflecting the `start` and defining the value of the first number of the first element of the list.

`HTMLOListElement.type`

A string value reflecting the `type` and defining the kind of marker to be used to display. It can have the following values:

* `'1'` meaning that decimal numbers are used: `1`, `2`, `3`, `4`, `5`, …
* `'a'` meaning that the lowercase latin alphabet is used: `a`, `b`, `c`, `d`, `e`, …
* `'A'` meaning that the uppercase latin alphabet is used: `A`, `B`, `C`, `D`, `E`, …
* `'i'` meaning that the lowercase latin numerals are used: `i`, `ii`, `iii`, `iv`, `v`, …
* `'I'` meaning that the uppercase latin numerals are used: `I`, `II`, `III`, `IV`, `V`, …

`HTMLOListElement.compact`
Deprecated

A boolean value indicating that spacing between list items should be reduced. This property reflects the `compact` attribute only, it doesn't consider the `line-height` CSS property used for that behavior in modern pages.

Instance methods
----------------

*No specific method; inherits methods from its parent, `HTMLElement`.*

Specifications
--------------

| Specification |
| --- |
| HTML Standard # htmlolistelement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The HTML element implementing this interface: `<ol>`.


SVGMissingGlyphElement - Web APIs

SVGMissingGlyphElement
======================

**Deprecated:** This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The **`SVGMissingGlyphElement`** interface corresponds to the `<missing-glyph>` elements.

Object-oriented access to the attributes of the `<missing-glyph>` element via the SVG DOM is not possible.

Instance properties
-------------------

*This interface has no properties but inherits properties from its parent, `SVGElement`.*

Instance methods
----------------

*This interface has no methods but inherits methods from its parent, `SVGElement`.*

Specifications
--------------

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 1.1 (Second Edition) # InterfaceSVGMissingGlyphElement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `<missing-glyph>`


USB - Web APIs

USB
===

Limited availability
--------------------

This feature is not Baseline because it does not work in some of the most widely-used browsers.

* Learn more
* See full compatibility
* Report feedback
**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

**Secure context:** This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

The **`USB`** interface of the WebUSB API provides attributes and methods for finding and connecting USB devices from a web page.

Use `navigator.usb` to get access to the `USB` object.

The USB interface inherits from `EventTarget`.

EventTarget

USBInstance properties
-------------------

None.

Instance methods
----------------

`USB.getDevices()`
Experimental

Returns a `Promise` that resolves with an array of `USBDevice` objects for paired attached devices.

`USB.requestDevice()`
Experimental

Returns a `Promise` that resolves with an instance of `USBDevice` if the specified device is found. Calling this function triggers the user agent's pairing flow.

Events
------

`connect`
Experimental

Fired whenever a previously paired device is connected.

`disconnect`
Experimental

Fired whenever a paired device is disconnected.

Specifications
--------------

| Specification |
| --- |
| WebUSB API # usb |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TouchEvent - Web APIs

TouchEvent
==========

The **`TouchEvent`** interface represents an `UIEvent` which is sent when the state of contacts with a touch-sensitive surface changes. This surface can be a touch screen or trackpad, for example. The event can describe one or more points of contact with the screen and includes support for detecting movement, addition and removal of contact points, and so forth.

Touches are represented by the `Touch` object; each touch is described by a position, size and shape, amount of pressure, and target element. Lists of touches are represented by `TouchList` objects.

Event

UIEvent

TouchEventConstructor
-----------

`TouchEvent()`

Creates a `TouchEvent` object.

Instance properties
-------------------

*This interface inherits properties from its parent, `UIEvent` and `Event`.*

`TouchEvent.altKey` Read only

A Boolean value indicating whether or not the alt key was down when the touch event was fired.

`TouchEvent.changedTouches` Read only

A `TouchList` of all the `Touch` objects representing individual points of contact whose states changed between the previous touch event and this one.

`TouchEvent.ctrlKey` Read only

A Boolean value indicating whether or not the control key was down when the touch event was fired.

`TouchEvent.metaKey` Read only

A Boolean value indicating whether or not the meta key was down when the touch event was fired.

`TouchEvent.shiftKey` Read only

A Boolean value indicating whether or not the shift key was down when the touch event was fired.

`TouchEvent.targetTouches` Read only

A `TouchList` of all the `Touch` objects that are both currently in contact with the touch surface **and** were also started on the same element that is the target of the event.

`TouchEvent.touches` Read only

A `TouchList` of all the `Touch` objects representing all current points of contact with the surface, regardless of target or changed status.

`TouchEvent.rotation`
Non-standard
 Read only

Change in rotation (in degrees) since the event's beginning. Positive values indicate clockwise rotation; negative values indicate counterclockwise rotation. Initial value: `0.0`.

`TouchEvent.scale`
Non-standard
 Read only

Distance between two digits since the event's beginning. Expressed as a floating-point multiple of the initial distance between the digits at the beginning of the event. Values below 1.0 indicate an inward pinch (zoom out). Values above 1.0 indicate an outward unpinch (zoom in). Initial value: `1.0`.

Touch event types
-----------------

There are several types of event that can be fired to indicate that touch-related changes have occurred. You can determine which of these has happened by looking at the event's `TouchEvent.type` property.

`touchstart`

 Sent when the user places a touch point on the touch surface.
 The event's target will be the `element` in which the touch occurred.

`touchend`

 Sent when the user removes a touch point from the surface;
 that is, when they lift a finger or stylus from the surface.
 This is also sent
 if the touch point moves off the edge of the surface;
 for example, if the user's finger slides off the edge of the screen.

 The event's target is the same `element`
 that received the `touchstart` event
 corresponding to the touch point,
 even if the touch point has moved outside that element.

 The touch point (or points)
 that were removed from the surface
 can be found in the `TouchList`
 specified by the `changedTouches` attribute.

`touchmove`

 Sent when the user moves a touch point along the surface.
 The event's target is the same `element`
 that received the `touchstart` event corresponding to the touch point,
 even if the touch point has moved outside that element.

 This event is also sent
 if the values of the radius, rotation angle, or force attributes of a touch point change.

**Note:** The rate at which `touchmove` events is sent is browser-specific, and may also vary depending on the capability of the user's hardware. You must not rely on a specific granularity of these events.

`touchcancel`

 Sent when a touch point has been disrupted in some way.
 There are several possible reasons why this might happen
 (and the exact reasons will vary from device to device, as well as browser to browser):

* An event of some kind occurred that canceled the touch; this might happen if a modal alert pops up during the interaction.
* The touch point has left the document window and moved into the browser's UI area, a plug-in, or other external content.
* The user has placed more touch points on the screen than can be supported, in which case the earliest `Touch` in the `TouchList` gets canceled.

### Using with addEventListener() and preventDefault()

It's important to note that in many cases, both touch and mouse events get sent (in order to let non-touch-specific code still interact with the user). If you use touch events, you should call `preventDefault()` to keep the mouse event from being sent as well.

The exception to this is Chrome, starting with version 56 (desktop, Chrome for Android, and Android webview), where the default value for the `passive` option for `touchstart` and `touchmove` is `true` and calls to `preventDefault()` will have no effect. To override this behavior, you need to set the `passive` option to `false`, after which calling `preventDefault()` will work as specified. The change to treat listeners as `passive` by default prevents the listener from blocking page rendering while a user is scrolling. A demo is available on the Chrome Developer site.

Example
-------

See the example on the main Touch events article.

Specifications
--------------

| Specification |
| --- |
| Touch Events # touchevent-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Touch events
* `GestureEvent`


RTCCertificate - Web APIs

RTCCertificate
==============

The **`RTCCertificate`** interface of the WebRTC API provides an object representing a certificate that an `RTCPeerConnection` uses to authenticate.

`RTCCertificate` is a serializable object, so it can be cloned with `structuredClone()` or copied between Workers using `postMessage()`.

Instance properties
-------------------

`RTCCertificate.expires` Read only

Returns the expiration date of the certificate.

Instance methods
----------------

`RTCCertificate.getFingerprints()`

Returns an array of certificate fingerprints, calculated using the different algorithms supported by the browser.

Specifications
--------------

| Specification |
| --- |
| WebRTC: Real-Time Communication in Browsers # dom-rtccertificate |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `RTCPeerConnection.RTCPeerConnection()` argument `configuration.certificates`
* `RTCPeerConnection.generateCertificate()`


Touch events - Web APIs

Touch events
============

To provide quality support for touch-based user interfaces, touch events offer the ability to interpret finger (or stylus) activity on touch screens or trackpads.

The touch events interfaces are relatively low-level APIs that can be used to support application-specific multi-touch interactions such as a two-finger gesture. A multi-touch interaction starts when a finger (or stylus) first touches the contact surface. Other fingers may subsequently touch the surface and optionally move across the touch surface. The interaction ends when the fingers are removed from the surface. During this interaction, an application receives touch events during the start, move, and end phases.

Touch events are similar to mouse events except they support simultaneous touches and at different locations on the touch surface. The `TouchEvent` interface encapsulates all of the touchpoints that are currently active. The `Touch` interface, which represents a single touchpoint, includes information such as the position of the touch point relative to the browser viewport.

Definitions
-----------

Surface

The touch-sensitive surface. This may be a screen or trackpad.

Touch point

A point of contact with the surface. This may be a finger (or elbow, ear, nose, whatever, but typically a finger) or stylus.

Interfaces
----------

`TouchEvent`

Represents an event that occurs when the state of touches on the surface changes.

`Touch`

Represents a single point of contact between the user and the touch surface.

`TouchList`

Represents a group of touches; this is used when the user has, for example, multiple fingers on the surface at the same time.

Example
-------

This example tracks multiple touchpoints at a time, allowing the user to draw in a `<canvas>` with more than one finger at a time. It will only work on a browser that supports touch events.

**Note:** The text below uses the term "finger" when describing the contact with the surface, but it could, of course, also be a stylus or other contact method.

### Create a canvas

```html
<canvas id="canvas" width="600" height="600" style="border:solid black 1px;">
  Your browser does not support canvas element.
</canvas>
<br />
Log:
<pre id="log" style="border: 1px solid #ccc;"></pre>
```

```css
#log {
  height: 200px;
  width: 600px;
  overflow: scroll;
}
```

### Setting up the event handlers

 When the page loads, the `startup()` function shown below will be called.
 This sets up all the event listeners for our `<canvas>` element so we can handle the touch events as they occur.

```js
function startup() {
  const el = document.getElementById("canvas");
  el.addEventListener("touchstart", handleStart);
  el.addEventListener("touchend", handleEnd);
  el.addEventListener("touchcancel", handleCancel);
  el.addEventListener("touchmove", handleMove);
  log("Initialized.");
}

document.addEventListener("DOMContentLoaded", startup);
```

#### Tracking new touches

We'll keep track of the touches in-progress.

```js
const ongoingTouches = [];
```

When a `touchstart` event occurs, indicating that a new touch on the surface has occurred, the `handleStart()` function below is called.

```js
function handleStart(evt) {
  evt.preventDefault();
  log("touchstart.");
  const el = document.getElementById("canvas");
  const ctx = el.getContext("2d");
  const touches = evt.changedTouches;

  for (let i = 0; i < touches.length; i++) {
    log(`touchstart: ${i}.`);
    ongoingTouches.push(copyTouch(touches[i]));
    const color = colorForTouch(touches[i]);
    log(`color of touch with id ${touches[i].identifier} = ${color}`);
    ctx.beginPath();
    ctx.arc(touches[i].pageX, touches[i].pageY, 4, 0, 2 \* Math.PI, false); // a circle at the start
    ctx.fillStyle = color;
    ctx.fill();
  }
}
```

This calls `event.preventDefault()` to keep the browser from continuing to process the touch event (this also prevents a mouse event from also being delivered). Then we get the context and pull the list of changed touch points out of the event's `TouchEvent.changedTouches` property.

After that, we iterate over all the `Touch` objects in the list, pushing them onto an array of active touchpoints and drawing the start point for the draw as a small circle; we're using a 4-pixel wide line, so a 4-pixel radius circle will show up neatly.

#### Drawing as the touches move

Each time one or more fingers move, a `touchmove` event is delivered, resulting in our `handleMove()` function being called. Its responsibility in this example is to update the cached touch information and to draw a line from the previous position to the current position of each touch.

```js
function handleMove(evt) {
  evt.preventDefault();
  const el = document.getElementById("canvas");
  const ctx = el.getContext("2d");
  const touches = evt.changedTouches;

  for (let i = 0; i < touches.length; i++) {
    const color = colorForTouch(touches[i]);
    const idx = ongoingTouchIndexById(touches[i].identifier);

    if (idx >= 0) {
      log(`continuing touch ${idx}`);
      ctx.beginPath();
      log(
        `ctx.moveTo( ${ongoingTouches[idx].pageX}, ${ongoingTouches[idx].pageY} );`,
      );
      ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
      log(`ctx.lineTo( ${touches[i].pageX}, ${touches[i].pageY} );`);
      ctx.lineTo(touches[i].pageX, touches[i].pageY);
      ctx.lineWidth = 4;
      ctx.strokeStyle = color;
      ctx.stroke();

      ongoingTouches.splice(idx, 1, copyTouch(touches[i])); // swap in the new touch record
    } else {
      log("can't figure out which touch to continue");
    }
  }
}
```

This iterates over the changed touches as well, but it looks in our cached touch information array for the previous information about each touch to determine the starting point for each touch's new line segment to be drawn. This is done by looking at each touch's `Touch.identifier` property. This property is a unique integer for each touch and remains consistent for each event during the duration of each finger's contact with the surface.

This lets us get the coordinates of the previous position of each touch and use the appropriate context methods to draw a line segment joining the two positions together.

After drawing the line, we call `Array.splice()` to replace the previous information about the touchpoint with the current information in the `ongoingTouches` array.

#### Handling the end of a touch

When the user lifts a finger off the surface, a `touchend` event is sent. We handle this by calling the `handleEnd()` function below. Its job is to draw the last line segment for each touch that ended and remove the touchpoint from the ongoing touch list.

```js
function handleEnd(evt) {
  evt.preventDefault();
  log("touchend");
  const el = document.getElementById("canvas");
  const ctx = el.getContext("2d");
  const touches = evt.changedTouches;

  for (let i = 0; i < touches.length; i++) {
    const color = colorForTouch(touches[i]);
    let idx = ongoingTouchIndexById(touches[i].identifier);

    if (idx >= 0) {
      ctx.lineWidth = 4;
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
      ctx.lineTo(touches[i].pageX, touches[i].pageY);
      ctx.fillRect(touches[i].pageX - 4, touches[i].pageY - 4, 8, 8); // and a square at the end
      ongoingTouches.splice(idx, 1); // remove it; we're done
    } else {
      log("can't figure out which touch to end");
    }
  }
}
```

This is very similar to the previous function; the only real differences are that we draw a small square to mark the end and that when we call `Array.splice()`, we remove the old entry from the ongoing touch list, without adding in the updated information. The result is that we stop tracking that touchpoint.

#### Handling canceled touches

If the user's finger wanders into browser UI, or the touch otherwise needs to be canceled, the `touchcancel` event is sent, and we call the `handleCancel()` function below.

```js
function handleCancel(evt) {
  evt.preventDefault();
  log("touchcancel.");
  const touches = evt.changedTouches;

  for (let i = 0; i < touches.length; i++) {
    let idx = ongoingTouchIndexById(touches[i].identifier);
    ongoingTouches.splice(idx, 1); // remove it; we're done
  }
}
```

Since the idea is to immediately abort the touch, we remove it from the ongoing touch list without drawing a final line segment.

### Convenience functions

This example uses two convenience functions that should be looked at briefly to help make the rest of the code more clear.

#### Selecting a color for each touch

 To make each touch's drawing look different, the `colorForTouch()` function is used to pick a color based on the touch's unique identifier.
 This identifier is an opaque number, but we can at least rely on it differing between the currently-active touches.

```js
function colorForTouch(touch) {
  let r = touch.identifier % 16;
  let g = Math.floor(touch.identifier / 3) % 16;
  let b = Math.floor(touch.identifier / 7) % 16;
  r = r.toString(16); // make it a hex digit
  g = g.toString(16); // make it a hex digit
  b = b.toString(16); // make it a hex digit
  const color = `#${r}${g}${b}`;
  return color;
}
```

 The result from this function is a string that can be used when calling `<canvas>` functions to set drawing colors.
 For example, for a `Touch.identifier` value of 10, the resulting string is "#a31".

#### Copying a touch object

Some browsers (mobile Safari, for one) re-use touch objects between events, so it's best to copy the properties you care about, rather than referencing the entire object.

```js
function copyTouch({ identifier, pageX, pageY }) {
  return { identifier, pageX, pageY };
}
```

#### Finding an ongoing touch

The `ongoingTouchIndexById()` function below scans through the `ongoingTouches` array to find the touch matching the given identifier then returns that touch's index into the array.

```js
function ongoingTouchIndexById(idToFind) {
  for (let i = 0; i < ongoingTouches.length; i++) {
    const id = ongoingTouches[i].identifier;

    if (id === idToFind) {
      return i;
    }
  }
  return -1; // not found
}
```

#### Showing what's going on

```js
function log(msg) {
  const container = document.getElementById("log");
  container.textContent = `${msg} \n${container.textContent}`;
}
```

### Result

You can test this example on mobile devices by touching the box below.

**Note:** More generally, the example will work on platforms that provide touch events.
 You can test this on desktop platforms that can simulate such events:

* On Firefox enable "touch simulation" in Responsive Design Mode (you may need to reload the page).
* On Chrome use Device mode and set the Device type to one that sends touch events.

Additional tips
---------------

This section provides additional tips on how to handle touch events in your web application.

### Handling clicks

Since calling `preventDefault()` on a `touchstart` or the first `touchmove` event of a series prevents the corresponding mouse events from firing, it's common to call `preventDefault()` on `touchmove` rather than `touchstart`. That way, mouse events can still fire and things like links will continue to work. Alternatively, some frameworks have taken to re-firing touch events as mouse events for this same purpose. (This example is oversimplified and may result in strange behavior. It is only intended as a guide.)

```js
function onTouch(evt) {
  evt.preventDefault();
  if (
    evt.touches.length > 1 ||
    (evt.type === "touchend" && evt.touches.length > 0)
  )
    return;

  const newEvt = document.createEvent("MouseEvents");
  let type = null;
  let touch = null;

  switch (evt.type) {
    case "touchstart":
      type = "mousedown";
      touch = evt.changedTouches[0];
      break;
    case "touchmove":
      type = "mousemove";
      touch = evt.changedTouches[0];
      break;
    case "touchend":
      type = "mouseup";
      touch = evt.changedTouches[0];
      break;
  }

  newEvt.initMouseEvent(
    type,
    true,
    true,
    evt.originalTarget.ownerDocument.defaultView,
    0,
    touch.screenX,
    touch.screenY,
    touch.clientX,
    touch.clientY,
    evt.ctrlKey,
    evt.altKey,
    evt.shiftKey,
    evt.metaKey,
    0,
    null,
  );
  evt.originalTarget.dispatchEvent(newEvt);
}
```

### Calling preventDefault() only on a second touch

One technique for preventing things like `pinchZoom` on a page is to call `preventDefault()` on the second touch in a series. This behavior is not well defined in the touch events spec and results in different behavior for different browsers (i.e., iOS will prevent zooming but still allow panning with both fingers; Android will allow zooming but not panning; Opera and Firefox currently prevent all panning and zooming.) Currently, it's not recommended to depend on any particular behavior in this case, but rather to depend on meta viewport to prevent zooming.

Specifications
--------------

| Specification |
| --- |
| Touch Events  |

Browser compatibility
---------------------

Touch events are typically available on devices with a touch screen, but many browsers make the touch events API unavailable on all desktop devices, even those with touch screens.

The reason for this is that some websites use the availability of parts of the touch events API as an indicator that the browser is running on a mobile device. If the touch events API is available, these websites will assume a mobile device and serve mobile-optimized content. This may then provide a poor experience for users of desktop devices that have touch screens.

To support both touch and mouse across all types of devices, use pointer events instead.

### api.Touch

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### api.TouchEvent

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### api.TouchList

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


SourceBufferList - Web APIs

SourceBufferList
================

The **`SourceBufferList`** interface represents a simple container list for multiple `SourceBuffer` objects.

The source buffer list containing the `SourceBuffer`s appended to a particular `MediaSource` can be retrieved using the `MediaSource.sourceBuffers` property.

The individual source buffers can be accessed using the bracket notation `[]`.

EventTarget

SourceBufferListInstance properties
-------------------

`SourceBufferList.length` Read only

Returns the number of `SourceBuffer` objects in the list.

Instance methods
----------------

*Inherits methods from its parent interface, `EventTarget`.*

Events
------

`addsourcebuffer`

Fired when a `SourceBuffer` is added to the list.

`removesourcebuffer`

Fired when a `SourceBuffer` is removed from the list.

Examples
--------

This example shows how to access the active source buffers of the `MediaSource` connected to an already playing `HTMLVideoElement`.

```js
// Video is an already playing video using a MediaSource srcObject
const video = document.querySelector("video");
const mediaSource = video.srcObject;
const sourceBufferList = mediaSource.activeSourceBuffers;
for (const sourceBuffer of sourceBufferList) {
  // Do something with each SourceBuffer, such as call abort()
  sourceBuffer.abort();
}
```

Specifications
--------------

| Specification |
| --- |
| Media Source Extensions™ # sourcebufferlist |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `MediaSource`
* `SourceBuffer`


SVGFontElement - Web APIs

SVGFontElement
==============

**Deprecated:** This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The **`SVGFontElement`** interface corresponds to the `<font>` elements.

Object-oriented access to the attributes of the `<font>` element via the SVG DOM is not possible.

Instance properties
-------------------

*This interface has no properties but inherits properties from its parent, `SVGElement`.*

Instance methods
----------------

*This interface has no methods but inherits methods from its parent, `SVGElement`.*

Specifications
--------------

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 1.1 (Second Edition) # InterfaceSVGFontElement |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `<font>` SVG Element


MediaCapabilities - Web APIs

MediaCapabilities
=================

The **`MediaCapabilities`** interface of the Media Capabilities API provides information about the decoding abilities of the device, system and browser. The API can be used to query the browser about the decoding abilities of the device based on codecs, profile, resolution, and bitrates. The information can be used to serve optimal media streams to the user and determine if playback should be smooth and power efficient.

The information is accessed through the **`mediaCapabilities`** property of the `Navigator` interface.

Instance methods
----------------

`MediaCapabilities.encodingInfo()`

When passed a valid media configuration, it returns a promise with information as to whether the media type is supported, and whether encoding such media would be smooth and power efficient.

`MediaCapabilities.decodingInfo()`

When passed a valid media configuration, it returns a promise with information as to whether the media type is supported, and whether decoding such media would be smooth and power efficient.

Specifications
--------------

| Specification |
| --- |
| Media Capabilities # media-capabilities-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* HTMLMediaElement's method canPlayType()
* MediaSource's method isTypeSupported()
* `Navigator` interface


WEBGL_color_buffer_float extension - Web APIs

WEBGL\_color\_buffer\_float extension
=====================================

The **`WEBGL_color_buffer_float`** extension is part of the WebGL API and adds the ability to render to 32-bit floating-point color buffers.

WebGL extensions are available using the `WebGLRenderingContext.getExtension()` method. For more information, see also Using Extensions in the WebGL tutorial.

**Note:** This extension is available to WebGL 1 contexts only. For WebGL 2, use the `EXT_color_buffer_float` extension.

The `OES_texture_float` extension implicitly enables this extension.

Constants
---------

`ext.RGBA32F_EXT`

RGBA 32-bit floating-point color-renderable format.

`ext.RGB32F_EXT` (
Deprecated
)

RGB 32-bit floating-point color-renderable format.

`ext.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT`

?

`ext.UNSIGNED_NORMALIZED_EXT`

?

Extended methods
----------------

This extension extends `WebGLRenderingContext.renderbufferStorage()`:

* The `internalformat` parameter now accepts `ext.RGBA32F_EXT` and `ext.RGB32F_EXT` (
Deprecated
).
Examples
--------

```js
const ext = gl.getExtension("WEBGL\_color\_buffer\_float");

gl.renderbufferStorage(gl.RENDERBUFFER, ext.RGBA32F\_EXT, 256, 256);
```

Specifications
--------------

| Specification |
| --- |
| WebGL WEBGL\_color\_buffer\_float Extension Specification  |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `WebGLRenderingContext.getExtension()`
* `WebGLRenderingContext.renderbufferStorage()`
* `OES_texture_float`


Local Font Access API - Web APIs

Local Font Access API
=====================

**Experimental:** **This is an experimental technology**
Check the Browser compatibility table carefully before using this in production.

The **Local Font Access API** provides a mechanism to access the user's locally installed font data — this includes higher-level details such as names, styles, and families, as well as the raw bytes of the underlying font files.

Concepts and usage
------------------

Web fonts were revolutionary in enabling typography on the web by allowing web designers to provide custom fonts to use on a web document. Specified via the `@font-face` at-rule, a web font can be loaded from a URL provided in the `url()` function.

`@font-face` has several other useful features available. In particular, you can also specify the font's full or Postscript name inside the `local()` function to tell the browser to use a local copy if the user has the font installed on their computer. This is not without its problems — `local()` has become notorious as a fingerprinting vector.

In addition, high-end design tools have historically been difficult to deliver on the web, due to challenges in accurate font enumeration and accessing low-level font data (for example, to apply filters and transformations). Current apps often rely on workarounds such as asking users to upload their fonts to a server where they are processed to get raw byte data, or installing a separate local program to provide additional capabilities.

The Local Font Access API has been created to address these problems.

The `Window.queryLocalFonts()` method provides access to an array of locally-installed fonts, each represented by a `FontData` object instance. `FontData` has several properties providing access to names, styles, and families, and it also has a `blob()` method providing access to a `Blob` containing the raw bytes of the underlying font file.

In terms of privacy and security:

* The Local Font Access API is designed to only provide access to the data required to solve the above problems. There is also no requirement for browsers to provide the full list of available local fonts, nor to provide the data in the same order as it appears on disk.
* When `Window.queryLocalFonts()` is invoked, the user is asked for permission to access their local fonts. The status of this permission can be queried via the `Permissions API` (the `local-fonts` permission).
* You can control access to this feature using a `local-fonts` Permissions Policy.
Interfaces
----------

`FontData`

Represents a single local font face.

Extensions to other interfaces
------------------------------

`Window.queryLocalFonts()`

Returns a `Promise` that fulfills with an array of `FontData` objects representing the font faces available locally.

Examples
--------

For a working live demo, see Font Select Demo.

### Feature detection

```js
if ("queryLocalFonts" in window) {
  // The Local Font Access API is supported
}
```

### Font enumeration

The following snippet will query for all available fonts, and log metadata. This could be used, for example, to populate a font-picker control.

```js
async function logFontData() {
  try {
    const availableFonts = await window.queryLocalFonts();
    for (const fontData of availableFonts) {
      console.log(fontData.postscriptName);
      console.log(fontData.fullName);
      console.log(fontData.family);
      console.log(fontData.style);
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
}
```

### Accessing low-level data

The `blob()` method provides access to low-level SFNT data — this is a font file format that can contain other font formats, such as PostScript, TrueType, OpenType, or Web Open Font Format (WOFF).

```js
async function computeOutlineFormat() {
  try {
    const availableFonts = await window.queryLocalFonts({
      postscriptNames: ["ComicSansMS"],
    });
    for (const fontData of availableFonts) {
      // `blob()` returns a Blob containing valid and complete
      // SFNT-wrapped font data.
      const sfnt = await fontData.blob();
      // Slice out only the bytes we need: the first 4 bytes are the SFNT
      // version info.
      // Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
      const sfntVersion = await sfnt.slice(0, 4).text();

      let outlineFormat = "UNKNOWN";
      switch (sfntVersion) {
        case "\x00\x01\x00\x00":
        case "true":
        case "typ1":
          outlineFormat = "truetype";
          break;
        case "OTTO":
          outlineFormat = "cff";
          break;
      }
      console.log("Outline format:", outlineFormat);
    }
  } catch (err) {
    console.error(err.name, err.message);
  }
}
```

Specifications
--------------

| Specification |
| --- |
| Local Font Access  |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* Use advanced typography with local fonts
* `@font-face`
* The `local-fonts` Permissions Policy directive


ResizeObserver - Web APIs

ResizeObserver
==============

The **`ResizeObserver`** interface reports changes to the dimensions of an `Element`'s content or border box, or the bounding box of an `SVGElement`.

**Note:** The content box is the box in which content can be placed, meaning the border box minus the padding and border width. The border box encompasses the content, padding, and border. See The box model for further explanation.

Constructor
-----------

`ResizeObserver()`

Creates and returns a new `ResizeObserver` object.

Instance properties
-------------------

None.

Instance methods
----------------

`ResizeObserver.disconnect()`

Unobserves all observed `Element` targets of a particular observer.

`ResizeObserver.observe()`

Initiates the observing of a specified `Element`.

`ResizeObserver.unobserve()`

Ends the observing of a specified `Element`.

Examples
--------

In the resize-observer-text.html (see source) example, we use the resize observer to change the `font-size` of a header and paragraph as a slider's value is changed causing the containing `<div>` to change width. This shows that you can respond to changes in an element's size, even if they have nothing to do with the viewport.

We also provide a checkbox to turn the observer off and on. If it is turned off, the text will not change in response to the `<div>`'s width changing.

The JavaScript looks like so:

```js
const h1Elem = document.querySelector("h1");
const pElem = document.querySelector("p");
const divElem = document.querySelector("body > div");
const slider = document.querySelector('input[type="range"]');
const checkbox = document.querySelector('input[type="checkbox"]');

divElem.style.width = "600px";

slider.addEventListener("input", () => {
  divElem.style.width = `${slider.value}px`;
});

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      const contentBoxSize = entry.contentBoxSize[0];
      h1Elem.style.fontSize = `${Math.max(
 1.5,
 contentBoxSize.inlineSize / 200,
 )}rem`;
      pElem.style.fontSize = `${Math.max(
 1,
 contentBoxSize.inlineSize / 600,
 )}rem`;
    } else {
      h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentRect.width / 200,
 )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }

  console.log("Size changed");
});

resizeObserver.observe(divElem);

checkbox.addEventListener("change", () => {
  if (checkbox.checked) {
    resizeObserver.observe(divElem);
  } else {
    resizeObserver.unobserve(divElem);
  }
});
```

Observation Errors
------------------

Implementations following the specification invoke resize events before paint (that is, before the frame is presented to the user). If there was any resize event, style and layout are re-evaluated — which in turn may trigger more resize events. Infinite loops from cyclic dependencies are addressed by only processing elements deeper in the DOM during each iteration. Resize events that don't meet that condition are deferred to the next paint, and an error event is fired on the `Window` object, with the well-defined message string:

**ResizeObserver loop completed with undelivered notifications.**

Note that this only prevents user-agent lockup, not the infinite loop itself. For example, the following code will cause the width of `divElem` to grow indefinitely, with the above error message in the console repeating every frame:

```js
const divElem = document.querySelector("body > div");

const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    entry.target.style.width = entry.contentBoxSize[0].inlineSize + 10 + "px";
  }
});

window.addEventListener("error", function (e) {
  console.error(e.message);
});
```

As long as the error event does not fire indefinitely, resize observer will settle and produce a stable, likely correct, layout. However, visitors may see a flash of broken layout, as a sequence of changes expected to happen in a single frame is instead happening over multiple frames.

Specifications
--------------

| Specification |
| --- |
| Resize Observer # resize-observer-interface |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* The box model
* `PerformanceObserver`
* `IntersectionObserver` (part of the Intersection Observer API)
* Upcoming container queries may be a viable alternative for implementing responsive design.