Pointer events - Web APIs

Pointer events
==============

Much of today's web content assumes the user's pointing device will be a mouse. However, since many devices support other types of pointing input devices, such as pen/stylus and touch surfaces, extensions to the existing pointing device event models are needed. *Pointer events* address that need.

Pointer events are DOM events that are fired for a pointing device. They are designed to create a single DOM event model to handle pointing input devices such as a mouse, pen/stylus or touch (such as one or more fingers).

The *pointer* is a hardware-agnostic device that can target a specific set of screen coordinates. Having a single event model for pointers can simplify creating websites and applications and provide a good user experience regardless of the user's hardware. However, for scenarios when device-specific handling is desired, pointer events defines a `pointerType property` to inspect the device type which produced the event.

The events needed to handle generic pointer input are analogous to `mouse events` (`mousedown`/`pointerdown`, `mousemove`/`pointermove`, etc.). Consequently, pointer event types are intentionally similar to mouse event types.

Additionally, a pointer event contains the usual properties present in mouse events (client coordinates, target element, button states, etc.) in addition to new properties for other forms of input: pressure, contact geometry, tilt, etc. In fact, the `PointerEvent` interface inherits all of the `MouseEvent` properties, thus facilitating the migration of content from mouse events to pointer events.

Terminology
-----------

### active buttons state

The condition when a *pointer* has a non-zero value for the `buttons` property. For example, in the case of a pen, when the pen has physical contact with the digitizer, or at least one button is pressed while hovering.

### active pointer

Any *pointer* input device that can produce events. A pointer is considered active if it can still produce further events. For example, a pen that is a down state is considered active because it can produce additional events when the pen is lifted or moved.

### digitizer

A sensing device with a surface that can detect contact. Most commonly, the sensing device is a touch-enabled screen that can sense input from an input device such as a pen, stylus, or finger. Some sensing devices can detect the close proximity of the input device, and the state is expressed as a hover following the mouse.

### hit test

The process the browser uses to determine a target element for a pointer event. Typically, this is determined by considering the pointer's location and also the visual layout of elements in a document on screen media.

### pointer

A hardware-agnostic representation of input devices that can target a specific coordinate (or set of coordinates) on a screen. Examples of *pointer* input devices are mouse, pen/stylus, and touch contacts.

### pointer capture

Pointer capture allows the events for a pointer to be retargeted to a particular element other than the normal hit test result of the pointer's location.

### pointer event

A DOM `event` fired for a *pointer*.

Interfaces
----------

The primary interface is the `PointerEvent` interface which has a `constructor` plus several event types and associated global event handlers.

The standard also includes some extensions to the `Element` and `Navigator` interfaces.

The following sub-sections contain short descriptions of each interface and property.

### PointerEvent interface

The `PointerEvent` interface extends the `MouseEvent` interface and has the following properties.

`altitudeAngle` Read only
Experimental

Represents the angle between a transducer (a pointer or stylus) axis and the X-Y plane of a device screen.

`azimuthAngle` Read only
Experimental

Represents the angle between the Y-Z plane and the plane containing both the transducer (a pointer or stylus) axis and the Y axis.

`pointerId` Read only

A unique identifier for the pointer causing the event.

`width` Read only

The width (magnitude on the X axis), in CSS pixels, of the contact geometry of the pointer.

`height` Read only

the height (magnitude on the Y axis), in CSS pixels, of the contact geometry of the pointer.

`pressure` Read only

the normalized pressure of the pointer input in the range of `0` to `1`, where `0` and `1` represent the minimum and maximum pressure the hardware is capable of detecting, respectively.

`tangentialPressure` Read only

The normalized tangential pressure of the pointer input (also known as barrel pressure or cylinder stress) in the range `-1` to `1`, where `0` is the neutral position of the control.

`tiltX` Read only

The plane angle (in degrees, in the range of `-90` to `90`) between the Y–Z plane and the plane containing both the pointer (e.g. pen stylus) axis and the Y axis.

`tiltY` Read only

the plane angle (in degrees, in the range of `-90` to `90`) between the X–Z plane and the plane containing both the pointer (e.g. pen stylus) axis and the X axis.

`twist` Read only

The clockwise rotation of the pointer (e.g. pen stylus) around its major axis in degrees, with a value in the range `0` to `359`.

`pointerType` Read only

Indicates the device type that caused the event (mouse, pen, touch, etc.).

`isPrimary` Read only

Indicates if the pointer represents the primary pointer of this pointer type.

### Event types and Global Event Handlers

Pointer events have ten event types, seven of which have similar semantics to their mouse event counterparts (`down`, `up`, `move`, `over`, `out`, `enter`, and `leave`).

Below is a short description of each event type.

| Event | Description |
| --- | --- |
| `pointerover` | Fired when a pointer is moved into an element's hit test boundaries. |
| `pointerenter` | Fired when a pointer is moved into the hit test boundaries of an element or one of its descendants, including as a result of a `pointerdown` event from a device that does not support hover (see `pointerdown`). |
| `pointerdown` | Fired when a pointer becomes *active buttons state*. |
| `pointermove` | Fired when a pointer changes coordinates. This event is also used if the change in pointer state cannot be reported by other events. |
| `pointerup` | Fired when a pointer is no longer *active buttons state*. |
| `pointercancel` | A browser fires this event if it concludes the pointer will no longer be able to generate events (for example the related device is deactivated). |
| `pointerout` | Fired for several reasons including: pointer is moved out of the hit test boundaries of an element; firing the pointerup event for a device that does not support hover (see `pointerup`); after firing the `pointercancel` event (see `pointercancel`); when a pen stylus leaves the hover range detectable by the digitizer. |
| `pointerleave` | Fired when a pointer is moved out of the hit test boundaries of an element. For pen devices, this event is fired when the stylus leaves the hover range detectable by the digitizer. |
| `pointerrawupdate`
Experimental
 | Fired when a pointer changes any properties that don't fire `pointerdown` or `pointerup` events. |
| `gotpointercapture` | Fired when an element receives pointer capture. |
| `lostpointercapture` | Fired after pointer capture is released for a pointer. |

### Element extensions

There are three extensions to the `Element` interface:

`hasPointerCapture()`

Indicates whether the element on which it is invoked has pointer capture for the pointer identified by the given pointer ID.

`releasePointerCapture()`

Releases (stops) *pointer capture* that was previously set for a specific pointer event.

`setPointerCapture()`

Designates a specific element as the *capture target* of future pointer events.

### Navigator extension

The `Navigator.maxTouchPoints` property is used to determine the maximum number of simultaneous touch points that are supported at any single point in time.

Examples
--------

This section contains examples of basic usage of using the pointer events interfaces.

### Registering event handlers

This example registers a handler for every event type for the given element.

```html
<html lang="en">
  <script>
 function over\_handler(event) {}
 function enter\_handler(event) {}
 function down\_handler(event) {}
 function move\_handler(event) {}
 function up\_handler(event) {}
 function cancel\_handler(event) {}
 function out\_handler(event) {}
 function leave\_handler(event) {}
 function rawupdate\_handler(event) {}
 function gotcapture\_handler(event) {}
 function lostcapture\_handler(event) {}

 function init() {
 const el = document.getElementById("target");
 // Register pointer event handlers
 el.onpointerover = over\_handler;
 el.onpointerenter = enter\_handler;
 el.onpointerdown = down\_handler;
 el.onpointermove = move\_handler;
 el.onpointerup = up\_handler;
 el.onpointercancel = cancel\_handler;
 el.onpointerout = out\_handler;
 el.onpointerleave = leave\_handler;
 el.onpointerrawupdate = rawupdate\_handler;
 el.ongotpointercapture = gotcapture\_handler;
 el.onlostpointercapture = lostcapture\_handler;
 }
 </script>
  <body onload="init();">
    <div id="target">Touch me…</div>
  </body>
</html>
```

### Event properties

This example illustrates accessing all of a pointer event's properties.

```html
<html lang="en">
  <script>
 const id = -1;

 function process\_id(event) {
 // Process this event based on the event's identifier
 }
 function process\_mouse(event) {
 // Process the mouse pointer event
 }
 function process\_pen(event) {
 // Process the pen pointer event
 }
 function process\_touch(event) {
 // Process the touch pointer event
 }
 function process\_tilt(tiltX, tiltY) {
 // Tilt data handler
 }
 function process\_pressure(pressure) {
 // Pressure handler
 }
 function process\_non\_primary(event) {
 // Non primary handler
 }

 function down\_handler(ev) {
 // Calculate the touch point's contact area
 const area = ev.width \* ev.height;

 // Compare cached id with this event's id and process accordingly
 if (id === ev.identifier) process\_id(ev);

 // Call the appropriate pointer type handler
 switch (ev.pointerType) {
 case "mouse":
 process\_mouse(ev);
 break;
 case "pen":
 process\_pen(ev);
 break;
 case "touch":
 process\_touch(ev);
 break;
 default:
 console.log(`pointerType ${ev.pointerType} is not supported`);
 }

 // Call the tilt handler
 if (ev.tiltX !== 0 && ev.tiltY !== 0) process\_tilt(ev.tiltX, ev.tiltY);

 // Call the pressure handler
 process\_pressure(ev.pressure);

 // If this event is not primary, call the non primary handler
 if (!ev.isPrimary) process\_non\_primary(ev);
 }

 function init() {
 const el = document.getElementById("target");
 // Register pointerdown handler
 el.onpointerdown = down\_handler;
 }
 </script>
  <body onload="init();">
    <div id="target">Touch me…</div>
  </body>
</html>
```

Determining the Primary Pointer
-------------------------------

In some scenarios there may be multiple pointers (for example a device with both a touchscreen and a mouse), or a pointer that supports multiple contact points (for example a touchscreen that supports multiple finger touches). The application can use the `isPrimary` property to identify a master pointer among the set of *active pointers* for each pointer type. If an application only wants to support a primary pointer, it can ignore all pointer events that are not primary.

A mouse has only one pointer, so it will always be the primary pointer. For touch input, a pointer is considered primary if the user touched the screen when there were no other active touches. For pen and stylus input, a pointer is considered primary if the user's pen initially contacted the screen when there were no other active pens contacting the screen.

Determining button states
-------------------------

Some pointer devices (such as mouse and pen) support multiple buttons, and the button presses can be *chorded* (i.e. pressing an additional button while another button on the pointer device is already pressed).

To determine the state of button presses, pointer events uses the `button` and `buttons` properties of the `MouseEvent` interface (that `PointerEvent` inherits from).

The following table provides the values of `button` and `buttons` for the various device button states.

| Device Button State | button | buttons |
| --- | --- | --- |
| Neither buttons nor touch/pen contact changed since last event | `-1` | — |
| Mouse move with no buttons pressed, Pen moved while hovering with no buttons pressed | — | `0` |
| Left Mouse, Touch Contact, Pen contact | `0` | `1` |
| Middle Mouse | `1` | `4` |
| Right Mouse, Pen barrel button | `2` | `2` |
| X1 (back) Mouse | `3` | `8` |
| X2 (forward) Mouse | `4` | `16` |
| Pen eraser button | `5` | `32` |

**Note:** The `button` property indicates a change in the state of the button. However, as in the case of touch, when multiple events occur with one event, all of them have the same value.

Capturing the pointer
---------------------

Pointer capture allows events for a particular `pointer event` to be re-targeted to a particular element instead of the normal hit test at a pointer's location. This can be used to ensure that an element continues to receive pointer events even if the pointer device's contact moves off the element (for example by scrolling).

The following example shows pointer capture being set on an element.

```html
<html lang="en">
  <script>
 function downHandler(ev) {
 let el = document.getElementById("target");
 // Element 'target' will receive/capture further events
 el.setPointerCapture(ev.pointerId);
 }

 function init() {
 let el = document.getElementById("target");
 el.onpointerdown = downHandler;
 }
 </script>
  <body onload="init();">
    <div id="target">Touch me…</div>
  </body>
</html>
```

The following example shows a pointer capture being released (when a `pointercancel` event occurs. The browser does this automatically when a `pointerup` or `pointercancel` event occurs.

```html
<html lang="en">
  <script>
 function downHandler(ev) {
 let el = document.getElementById("target");
 // Element "target" will receive/capture further events
 el.setPointerCapture(ev.pointerId);
 }

 function cancelHandler(ev) {
 let el = document.getElementById("target");
 // Release the pointer capture
 el.releasePointerCapture(ev.pointerId);
 }

 function init() {
 let el = document.getElementById("target");
 // Register pointerdown and pointercancel handlers
 el.onpointerdown = downHandler;
 el.onpointercancel = cancelHandler;
 }
 </script>
  <body onload="init();">
    <div id="target">Touch me…</div>
  </body>
</html>
```

touch-action CSS property
-------------------------

The `touch-action` CSS property is used to specify whether or not the browser should apply its default (*native*) touch behavior (such as zooming or panning) to a region. This property may be applied to all elements except: non-replaced inline elements, table rows, row groups, table columns, and column groups.

A value of `auto` means the browser is free to apply its default touch behavior (to the specified region) and the value of `none` disables the browser's default touch behavior for the region. The values `pan-x` and `pan-y`, mean that touches that begin on the specified region are only for horizontal and vertical scrolling, respectively. The value `manipulation` means the browser may consider touches that begin on the element are only for scrolling and zooming.

In the following example, the browser's default touch behavior is disabled for the `div` element.

```html
<html lang="en">
  <body>
    <div style="touch-action:none;">Can't touch this…</div>
  </body>
</html>
```

In the following example, default touch behavior is disabled for some `button` elements.

```css
button#tiny {
  touch-action: none;
}
```

In the following example, when the `target` element is touched, it will only pan in the horizontal direction.

```css
#target {
  touch-action: pan-x;
}
```

Compatibility with mouse events
-------------------------------

Although the pointer event interfaces enable applications to create enhanced user experiences on pointer enabled devices, the reality is the vast majority of today's web content is designed to only work with mouse input. Consequently, even if a browser supports pointer events, the browser must still process mouse events so content that assumes mouse-only input will work as is without direct modification. Ideally, a pointer enabled application does not need to explicitly handle mouse input. However, because the browser must process mouse events, there may be some compatibility issues that need to be handled. This section contains information about pointer event and mouse event interaction and the ramifications for application developers.

The browser *may map generic pointer input to mouse events for compatibility with mouse-based content*. This mapping of events is called *compatibility mouse events*. Authors can prevent the production of certain compatibility mouse events by canceling the pointerdown event but note that:

* Mouse events can only be prevented when the pointer is down.
* Hovering pointers (e.g. a mouse with no buttons pressed) cannot have their mouse events prevented.
* The `mouseover`, `mouseout`, `mouseenter`, and `mouseleave` events are never prevented (even if the pointer is down).
Best practices
--------------

Here are some *best practices* to consider when using pointer events:

* Minimize the amount of work performed in event handlers.
* Add the event handlers to a specific target element (rather than the entire document or nodes higher up in the document tree).
* The target element (node) should be large enough to accommodate the largest contact surface area (typically a finger touch). If the target area is too small, touching it could result in firing other events for adjacent elements.
Specifications
--------------

| Specification |
| --- |
| Pointer Events  |

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

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

Some additional values have been defined for the `CSS touch-action` property as part of the Pointer Events specification, but currently those values have limited implementation support.

See also
--------

### Demos and examples

* Touch/pointer tests and demos (by Patrick H. Lauke)
### Community

* Pointer Events Working Group
* Mail list
* W3C #pointerevents IRC channel
### Related topics and resources

* Touch Events Standard


ClipboardEvent - Web APIs

ClipboardEvent
==============

The **`ClipboardEvent`** interface of the Clipboard API represents events providing information related to modification of the clipboard, that is `cut`, `copy`, and `paste` events.

Event

ClipboardEventConstructor
-----------

`ClipboardEvent()`

Creates a `ClipboardEvent` event with the given parameters.

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

*Also inherits properties from its parent `Event`*.

`ClipboardEvent.clipboardData` Read only

A `DataTransfer` object containing the data affected by the user-initiated `cut`, `copy`, or `paste` operation, along with its MIME type.

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

*No specific methods; inherits methods from its parent `Event`*.

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

| Specification |
| --- |
| Clipboard API and events # clipboard-event-interfaces |

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

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

See also
--------

* Copy-related events: `copy`, `cut`, `paste`
* Clipboard API
* Image support for Async Clipboard article


SpeechRecognition - Web APIs

SpeechRecognition
=================

The **`SpeechRecognition`** interface of the Web Speech API is the controller interface for the recognition service; this also handles the `SpeechRecognitionEvent` sent from the recognition service.

**Note:** On some browsers, like Chrome, using Speech Recognition on a web page involves a server-based recognition engine. Your audio is sent to a web service for recognition processing, so it won't work offline.

EventTarget

SpeechRecognitionConstructor
-----------

`SpeechRecognition()`

Creates a new `SpeechRecognition` object.

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

*`SpeechRecognition` also inherits properties from its parent interface, `EventTarget`.*

`SpeechRecognition.grammars`

Returns and sets a collection of `SpeechGrammar` objects that represent the grammars that will be understood by the current `SpeechRecognition`.

`SpeechRecognition.lang`

Returns and sets the language of the current `SpeechRecognition`. If not specified, this defaults to the HTML `lang` attribute value, or the user agent's language setting if that isn't set either.

`SpeechRecognition.continuous`

Controls whether continuous results are returned for each recognition, or only a single result. Defaults to single (`false`.)

`SpeechRecognition.interimResults`

Controls whether interim results should be returned (`true`) or not (`false`.) Interim results are results that are not yet final (e.g. the `SpeechRecognitionResult.isFinal` property is `false`.)

`SpeechRecognition.maxAlternatives`

Sets the maximum number of `SpeechRecognitionAlternative`s provided per result. The default value is 1.

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

*`SpeechRecognition` also inherits methods from its parent interface, `EventTarget`.*

`SpeechRecognition.abort()`

Stops the speech recognition service from listening to incoming audio, and doesn't attempt to return a `SpeechRecognitionResult`.

`SpeechRecognition.start()`

Starts the speech recognition service listening to incoming audio with intent to recognize grammars associated with the current `SpeechRecognition`.

`SpeechRecognition.stop()`

Stops the speech recognition service from listening to incoming audio, and attempts to return a `SpeechRecognitionResult` using the audio captured so far.

Events
------

Listen to these events using `addEventListener()` or by assigning an event listener to the `oneventname` property of this interface.

`audiostart`

 Fired when the user agent has started to capture audio.
 Also available via the `onaudiostart` property.

`audioend`

 Fired when the user agent has finished capturing audio.
 Also available via the `onaudioend` property.

`end`

 Fired when the speech recognition service has disconnected.
 Also available via the `onend` property.

`error`

 Fired when a speech recognition error occurs.
 Also available via the `onerror` property.

`nomatch`

 Fired when the speech recognition service returns a final result with no significant recognition. This may involve some degree of recognition, which doesn't meet or exceed the `confidence` threshold.
 Also available via the `onnomatch` property.

`result`

 Fired when the speech recognition service returns a result — a word or phrase has been positively recognized and this has been communicated back to the app.
 Also available via the `onresult` property.

`soundstart`

 Fired when any sound — recognizable speech or not — has been detected.
 Also available via the `onsoundstart` property.

`soundend`

 Fired when any sound — recognizable speech or not — has stopped being detected.
 Also available via the `onsoundend` property.

`speechstart`

 Fired when sound that is recognized by the speech recognition service as speech has been detected.
 Also available via the `onspeechstart` property.

`speechend`

 Fired when speech recognized by the speech recognition service has stopped being detected.
 Also available via the `onspeechend` property.

`start`

 Fired when the speech recognition service has begun listening to incoming audio with intent to recognize grammars associated with the current `SpeechRecognition`.
 Also available via the `onstart` property.

Examples
--------

In our simple Speech color changer example, we create a new `SpeechRecognition` object instance using the `SpeechRecognition()` constructor, create a new `SpeechGrammarList`, and set it to be the grammar that will be recognized by the `SpeechRecognition` instance using the `SpeechRecognition.grammars` property.

After some other values have been defined, we then set it so that the recognition service starts when a click event occurs (see `SpeechRecognition.start()`.) When a result has been successfully recognized, the `result` event fires, we extract the color that was spoken from the event object, and then set the background color of the `<html>` element to that color.

```js
const grammar =
  "#JSGF V1.0; grammar colors; public <color> = aqua | azure | beige | bisque | black | blue | brown | chocolate | coral | crimson | cyan | fuchsia | ghostwhite | gold | goldenrod | gray | green | indigo | ivory | khaki | lavender | lime | linen | magenta | maroon | moccasin | navy | olive | orange | orchid | peru | pink | plum | purple | red | salmon | sienna | silver | snow | tan | teal | thistle | tomato | turquoise | violet | white | yellow ;";
const recognition = new SpeechRecognition();
const speechRecognitionList = new SpeechGrammarList();
speechRecognitionList.addFromString(grammar, 1);
recognition.grammars = speechRecognitionList;
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 1;

const diagnostic = document.querySelector(".output");
const bg = document.querySelector("html");

document.body.onclick = () => {
  recognition.start();
  console.log("Ready to receive a color command.");
};

recognition.onresult = (event) => {
  const color = event.results[0][0].transcript;
  diagnostic.textContent = `Result received: ${color}`;
  bg.style.backgroundColor = color;
};
```

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

| Specification |
| --- |
| Web Speech API # speechreco-section |

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

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

See also
--------

* Web Speech API


DocumentType - Web APIs

DocumentType
============

The **`DocumentType`** interface represents a `Node` containing a doctype.

EventTarget

Node

DocumentTypeInstance properties
-------------------

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

`DocumentType.name` Read only

The type of the document. It is always `"html"` for HTML documents, but will vary for XML documents.

`DocumentType.publicId` Read only

A string with an identifier of the type of document. Always empty (`""`) for HTML, it will be, for example, `"-//W3C//DTD SVG 1.1//EN"` for SVG documents.

`DocumentType.systemId` Read only

A string containing the URL to the associated DTD. Always empty (`""`) for HTML, it will be, for example, `"http://www.w3.org/2000/svg"` for SVG documents.

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

*Inherits methods from its parent, `Node`.*

`DocumentType.after()`

 Inserts a set of `Node` or string objects in the children list of the
 object's parent, just after this node.

`DocumentType.before()`

 Inserts a set of `Node` or string objects in the children list of the
 object's parent, just before this node.

`DocumentType.remove()`

Removes this object from its parent children list.

`DocumentType.replaceWith()`

Replaces the document type with a set of given nodes.

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

| Specification |
| --- |
| DOM Standard # interface-documenttype |

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

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

See also
--------

* The DOM interfaces index.
* `DOMImplementation.createDocumentType()` to create a new `DocumentType` node.


LaunchParams - Web APIs

LaunchParams
============

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

The **`LaunchParams`** interface of the Launch Handler API is used when implementing custom launch navigation handling in a PWA. When `window.launchQueue.setConsumer()` is invoked to set up the launch navigation handling functionality, the callback function inside `setConsumer()` is passed a `LaunchParams` object instance.

Such custom navigation handling is initiated via `Window.launchQueue` when a PWA has been launched with a `launch_handler` `client_mode` value of `focus-existing`, `navigate-new`, or `navigate-existing`.

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

`LaunchParams.files` Read only
Experimental

Returns a read-only array of `FileSystemHandle` objects representing any files passed along with the launch navigation via the `POST` method.

`LaunchParams.targetURL` Read only
Experimental

Returns the target URL of the launch.

Examples
--------

```js
if ("launchQueue" in window) {
  window.launchQueue.setConsumer((launchParams) => {
    if (launchParams.targetURL) {
      const params = new URL(launchParams.targetURL).searchParams;

      // Assuming a music player app that gets a track passed to it to be played
      const track = params.get("track");
      if (track) {
        audio.src = track;
        title.textContent = new URL(track).pathname.substr(1);
        audio.play();
      }
    }
  });
}
```

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

| Specification |
| --- |
| Web App Launch Handler API # launchparams-interface |

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

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

See also
--------

* Launch Handler API: Control how your app is launched
* `Window.launchQueue`
* Musicr 2.0 demo app


SVGFontFaceFormatElement - Web APIs

SVGFontFaceFormatElement
========================

**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 **`SVGFontFaceFormatElement`** interface corresponds to the `<font-face-format>` elements.

Object-oriented access to the attributes of the `<font-face-format>` 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) # InterfaceSVGFontFaceFormatElement |

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

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

See also
--------

* `<font-face-format>`


XRReferenceSpace - Web APIs

XRReferenceSpace
================

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

The WebXR Device API's **`XRReferenceSpace`** interface describes the coordinate system for a specific tracked entity or object within the virtual world using a specified tracking behavior. The tracking behavior is defined by the selected reference space type. It expands upon the base class, `XRSpace`, by adding support for several different tracking behaviors as well as to request a new reference space which describes the offset transform between the tracked object and another location in the world.

All reference spaces—with the sole exception being bounded reference spaces—are described using the `XRReferenceSpace` type. Bounded spaces are implemented as `XRBoundedReferenceSpace` objects. These are special spaces which let you establish a perimeter within which it's "safe" for the viewer to move. For XR systems that allow the user to physically move around, such as those that track movement with a real-world camera, this boundary establishes the edges of the area the user is able to move around in, whether due to physical obstacles or due to limitations of the XR hardware. See the article Using bounded reference spaces to protect the viewer for more on using boundaries to keep the user from colliding with obstacles both physical and virtual.

EventTarget

XRSpace

XRReferenceSpaceInstance properties
-------------------

*`XRReferenceSpace` inherits the properties of `EventTarget` but defines no additional properties.*

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

*`XRReferenceSpace` also inherits methods from `EventTarget` in addition to the following methods.*

`getOffsetReferenceSpace()`

Creates and returns a new reference space object as the same type as the one on which you call the method (so, either `XRReferenceSpace` or `XRBoundedReferenceSpace`). The new reference space can be used to transform a coordinate from the reference space of the object on which the method is called into a different coordinate space. This is useful for positioning objects while rendering, and to perform the needed transforms when changing the viewer's position and/or orientation in 3D space.

Events
------

`reset`

The `reset` event is sent to an `XRReferenceSpace` object when the browser detects a discontinuity between the tracked object's origin and the user's environment or location. This can happen, for example, after the user recalibrates their XR device, or if the device automatically adjusts its origin after losing and regaining tracking.

Reference space types
---------------------

The types of reference space are listed in the table below, with brief information about their use cases and which interface is used to implement them.

`bounded-floor`

An `XRBoundedReferenceSpace` similar to the `local` type, except the user is not expected to move outside a predetermined boundary, given by the `boundsGeometry` in the returned object.

`local`

An `XRReferenceSpace` tracking space whose native origin is located near the viewer's position at the time the session was created. The exact position depends on the underlying platform and implementation. The user isn't expected to move much if at all beyond their starting position, and tracking is optimized for this use case. For devices with six degrees of freedom (6DoF) tracking, the `local` reference space tries to keep the origin stable relative to the environment.

`local-floor`

An `XRReferenceSpace` similar to the `local` type, except the starting position is placed in a safe location for the viewer to stand, where the value of the y axis is 0 at floor level. If that floor level isn't known, the user agent will estimate the floor level. If the estimated floor level is non-zero, the browser is expected to round it such a way as to avoid fingerprinting (likely to the nearest centimeter).

`unbounded`

An `XRReferenceSpace` tracking space which allows the user total freedom of movement, possibly over extremely long distances from their origin point. The viewer isn't tracked at all; tracking is optimized for stability around the user's current position, so the native origin may drift as needed to accommodate that need.

`viewer`

An `XRReferenceSpace` tracking space whose native origin tracks the viewer's position and orientation. This is used for environments in which the user can physically move around, and is supported by all instances of `XRSession`, both immersive and inline, though it's most useful for inline sessions. It's particularly useful when determining the distance between the viewer and an input, or when working with offset spaces. Otherwise, typically, one of the other reference space types will be used more often.

Usage notes
-----------

### Creating an XRReferenceSpace

There are two situations in which you need to obtain an `XRReferenceSpace`. The first is when you set up your scene and need to obtain a reference space to represent the user's viewpoint on the world for the duration of the `XRSession`. To do that, call the `XRSession` method `requestReferenceSpace()`, specifying the reference space type you wish to obtain.

```js
xrSession.requestReferenceSpace("local").then((refSpace) => {
  xrReferenceSpace = refSpace;
  // …
});
```

The other situation in which you may need to acquire a new reference space is if you need to move the origin to a new position; this is commonly done, for example, when your project allows the user to move through the environment using input devices such as the keyboard, mouse, touchpad, or game controls that are not connected through the XR device. Since the origin will typically be the user's location in the space, you need to change the origin to reflect their movement and any orientation changes they make.

To move or rotate the user's view of the world, you need to change the `XRReferenceSpace` used to represent that viewpoint. However, `XRReferenceSpace` is immutable, so you need to instead create a new reference space representing the changed viewpoint. This is easily done using the `getOffsetReferenceSpace()` method.

```js
let offsetTransform = new XRRigidTransform(
  { x: 2, y: 0, z: 1 },
  { x: 0, y: 0, z: 0, w: 1 },
);
xrReferenceSpace = xrReferenceSpace.getOffsetReferenceSpace(offsetTransform);
```

This replaces the `XRReferenceSpace` with a new one whose origin and orientation are adjusted to place the new origin at (2, 0, 1) relative to the current origin and rotated given a unit quaternion that orients the space to put the viewer facing straight up relative to the previous world orientation.

### Geometry

The native origin of any `XRReferenceSpace` is always configured so that +X is considered to be to the right, +Y is upward, and +Z is "backward" or toward the user.

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

| Specification |
| --- |
| WebXR Device API # xrreferencespace-interface |

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

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

See also
--------

* Fundamentals of WebXR
* Geometry and reference spaces in WebXR
* Viewpoints and viewers: Simulating cameras in WebXR
* Matrix math for the web
* Movement, orientation, and motion
* Using bounded reference spaces to protect the user


Gamepad - Web APIs

Gamepad
=======

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

The **`Gamepad`** interface of the Gamepad API defines an individual gamepad or other controller, allowing access to information such as button presses, axis positions, and id.

A Gamepad object can be returned in one of two ways: via the `gamepad` property of the `gamepadconnected` and `gamepaddisconnected` events, or by grabbing any position in the array returned by the `Navigator.getGamepads()` method.

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

`Gamepad.axes` Read only

An array representing the controls with axes present on the device (e.g. analog thumb sticks).

`Gamepad.buttons` Read only

An array of `gamepadButton` objects representing the buttons present on the device.

`Gamepad.connected` Read only

A boolean indicating whether the gamepad is still connected to the system.

`Gamepad.displayId` Read only
Deprecated

Non-standard

Returns the `VRDisplay.displayId` of an associated `VRDisplay` (if relevant) — the `VRDisplay` that the gamepad is controlling the displayed scene of.

`Gamepad.hand` Read only
Experimental

An enum defining what hand the controller is being held in, or is most likely to be held in.

`Gamepad.hapticActuators` Read only
Experimental

An array containing `GamepadHapticActuator` objects, each of which represents haptic feedback hardware available on the controller.

`Gamepad.vibrationActuator` Read only
Non-standard

A `GamepadHapticActuator` object, which represents haptic feedback hardware available on the controller.

`Gamepad.id` Read only

A string containing identifying information about the controller.

`Gamepad.index` Read only

An integer that is auto-incremented to be unique for each device currently connected to the system.

`Gamepad.mapping` Read only

A string indicating whether the browser has remapped the controls on the device to a known layout.

`Gamepad.pose` Read only
Experimental

A `GamepadPose` object representing the pose information associated with a WebVR controller (e.g. its position and orientation in 3D space).

`Gamepad.timestamp` Read only

A `DOMHighResTimeStamp` representing the last time the data for this gamepad was updated.

Example
-------

```js
window.addEventListener("gamepadconnected", (e) => {
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    e.gamepad.index,
    e.gamepad.id,
    e.gamepad.buttons.length,
    e.gamepad.axes.length,
  );
});
```

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

| Specification |
| --- |
| Gamepad # gamepad-interface |
| Gamepad Extensions # partial-gamepad-interface |

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

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

See also
--------

* Using the Gamepad API
* Gamepad API


XSLTProcessor - Web APIs

XSLTProcessor
=============

 An **`XSLTProcessor`** applies an XSLT stylesheet transformation to an XML document to
 produce a new XML document as output. It has methods to load the XSLT stylesheet, to
 manipulate `<xsl:param>` parameter values, and to apply the
 transformation to documents.

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

`XSLTProcessor()`

Create a new `XSLTProcessor`.

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

`XSLTProcessor.importStylesheet()`

 Imports the XSLT stylesheet.
 If the given node is a document node, you can pass in a full XSL Transform or a literal result element transform;
 otherwise, it must be an `<xsl:stylesheet>` or `<xsl:transform>` element.

`XSLTProcessor.transformToFragment()`

 Transforms the node source by applying the XSLT stylesheet imported using the `XSLTProcessor.importStylesheet()` function.
 The owner document of the resulting document fragment is the owner node.

`XSLTProcessor.transformToDocument()`

Transforms the node source applying the XSLT stylesheet given importing using the `XSLTProcessor.importStylesheet()` function.

`XSLTProcessor.setParameter()`

Sets a parameter (`<xsl:param>`) value in the XSLT stylesheet that was imported.

`XSLTProcessor.getParameter()`

Gets the value of a parameter from the XSLT stylesheet.

`XSLTProcessor.removeParameter()`

 Removes the parameter if it was previously set.
 This will make the `XSLTProcessor` use the default value for the parameter as specified in the XSLT stylesheet.

`XSLTProcessor.clearParameters()`

 Removes all set parameters from the `XSLTProcessor`.
 The `XSLTProcessor` will then use the default values specified in the XSLT stylesheet.

`XSLTProcessor.reset()`

Removes all parameters and stylesheets from the `XSLTProcessor`.

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

*This are no properties for this interface.*

Examples
--------

### Instantiating an `XSLTProcessor`

```js
async function init() {
  const parser = new DOMParser();
  const xsltProcessor = new XSLTProcessor();

  // Load the XSLT file, example1.xsl
  const xslResponse = await fetch("example1.xsl");
  const xslText = await xslResponse.text();
  const xslStylesheet = parser.parseFromString(xslText, "application/xml");
  xsltProcessor.importStylesheet(xslStylesheet);

  // process the file
  // ...
}
```

### Creating an XML document based on part of a document's DOM

For the actual transformation, `XSLTProcessor` requires an XML document, which is used in conjunction with the imported XSL file to produce the final result. The XML document can be a separate XML file loaded using `fetch()`, or it can be part of the existing page.

To process part of a page's DOM, it is necessary to first create an XML document in memory. Assuming that the DOM to be processed is contained by an element with the id `example`, that DOM can be "cloned" using the in-memory XML document's `Document.importNode()` method. `Document.importNode()` allows transferring a DOM fragment between documents, in this case from an HTML document to an XML document. The first parameter references the DOM node to clone. By making the second parameter "true", it will clone all descendants as well (a deep clone). The cloned DOM can then be inserted into the XML document using `Node.appendChild()`, as shown below.

```js
// Create a new XML document in memory
const xmlRef = document.implementation.createDocument("", "", null);

// We want to move a part of the DOM from an HTML document to an XML document.
// importNode is used to clone the nodes we want to process via XSLT - true makes it do a deep clone
const myNode = document.getElementById("example");
const clonedNode = xmlRef.importNode(myNode, true);

// Add the cloned DOM into the XML document
xmlRef.appendChild(clonedNode);
```

Once the stylesheet has been imported, `XSLTProcessor` has to perform two methods for the actual transformation, namely `XSLTProcessor.transformToDocument()` and `XSLTProcessor.transformToFragment()`. `XSLTProcessor.transformToDocument()` returns a full XML document while `XSLTProcessor.transformToFragment()` returns a document fragment that can be easily added to an existing document. Both take in the XML document as the first parameter that will be transformed. `XSLTProcessor.transformToFragment()` requires a second parameter, namely the document object that will own the generated fragment. If the generated fragment will be inserted into the current HTML document, passing in document is enough.

### Creating an XML document From a String 'XML Soup'

You can use the `DOMParser` to create an XML document from a string of XML.

```js
const parser = new DOMParser();
const doc = parser.parseFromString(aStr, "text/xml");
```

### Performing the transformation

```js
const fragment = xsltProcessor.transformToFragment(xmlRef, document);
```

### Basic Example

The basic example will load an XML file and apply a XSL transformation on it. These are the same files used in the Generating HTML example. The XML file describes an article and the XSL file formats the information for display.

#### XML

```xml
<?xml version="1.0"?>
<myNS:Article xmlns:myNS="http://devedge.netscape.com/2002/de">
  <myNS:Title>My Article</myNS:Title>
  <myNS:Authors>
    <myNS:Author company="Foopy Corp.">Mr. Foo</myNS:Author>
    <myNS:Author>Mr. Bar</myNS:Author>
  </myNS:Authors>
  <myNS:Body>
    The <b>rain</b> in <u>Spain</u> stays mainly in the plains.
  </myNS:Body>
</myNS:Article>
```

#### XSLT

```xml
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:myNS="http://devedge.netscape.com/2002/de">

  <xsl:output method="html" />

  <xsl:template match="/">
    <html>

      <head>

        <title>
          <xsl:value-of select="/myNS:Article/myNS:Title"/>
        </title>

        <style>
          .myBox {margin:10px 155px 0 50px; border: 1px dotted #639ACE; padding:0 5px 0 5px;}
        </style>

      </head>

      <body>
        <p class="myBox">
          <span class="title">
            <xsl:value-of select="/myNS:Article/myNS:Title"/>
          </span> <br />

          Authors:   <br />
            <xsl:apply-templates select="/myNS:Article/myNS:Authors/myNS:Author"/>
          </p>

        <p class="myBox">
          <xsl:apply-templates select="//myNS:Body"/>
        </p>

      </body>

    </html>
  </xsl:template>

  <xsl:template match="myNS:Author">
     --   <xsl:value-of select="." />

    <xsl:if test="@company">
     ::   <b>  <xsl:value-of select="@company" />  </b>
    </xsl:if>

    <br />
  </xsl:template>

  <xsl:template match="myNS:Body">
    <xsl:copy>
      <xsl:apply-templates select="@\*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@\*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@\*|node()"/>
      </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
```

The example loads both the .xsl (`xslStylesheet`) and the .xml (`xmlDoc`) files into memory. The .xsl file is then imported (`xsltProcessor.importStylesheet(xslStylesheet)`) and the transformation run (`xsltProcessor.transformToFragment(xmlDoc, document)`). This allows fetching of data after the page has been loaded, without initiating a fresh page load.

#### JavaScript

```js
async function init() {
  const parser = new DOMParser();
  const xsltProcessor = new XSLTProcessor();

  // Load the XSLT file, example1.xsl
  const xslResponse = await fetch("example1.xsl");
  const xslText = await xslResponse.text();
  const xslStylesheet = parser.parseFromString(xslText, "application/xml");
  xsltProcessor.importStylesheet(xslStylesheet);

  // Load the XML file, example1.xml
  const xmlResponse = await fetch("example1.xml");
  const xmlText = await xmlResponse.text();
  const xmlDoc = parser.parseFromString(xmlText, "application/xml");

  const fragment = xsltProcessor.transformToFragment(xmlDoc, document);

  document.getElementById("example").textContent = "";
  document.getElementById("example").appendChild(fragment);
}

init();
```

### Advanced example

This advanced example sorts several divs based on their content. The example allows sorting the content multiple times, alternating between ascending and descending order. The JavaScript loads the .xsl file only on the first sort and sets the `xslloaded` variable to true once it has finished loading the file. Using the `XSLTProcessor.getParameter()` method, the code can figure whether to sort in ascending or descending order. It defaults to ascending if the parameter is empty (the first time the sorting happens, as there is no value for it in the XSLT file). The sorting value is set using `XSLTProcessor.setParameter()`.

The XSLT file has a parameter called `myOrder` that JavaScript sets to change the sorting method. The `xsl:sort` element's order attribute can access the value of the parameter using `$myOrder`. However, the value needs to be an XPATH expression and not a string, so `{$myOrder}` is used. Using {} evaluates the content as an XPath expression.

Once the transformation is complete, the result is appended to the document, as shown in this example.

#### XHTML

```html
<div id="example">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
</div>
```

#### JavaScript

```js
let xslRef;
let xslloaded = false;
const parser = new DOMParser();
const xsltProcessor = new XSLTProcessor();
let myDOM;

let xmlRef = document.implementation.createDocument("", "", null);

async function sort() {
  if (!xslloaded) {
    const response = await fetch("example2.xsl");
    const xslText = await response.text();
    xslRef = parser.parseFromString(xslText, "application/xml");
    xsltProcessor.importStylesheet(xslRef);
    xslloaded = true;
  }

  // Create a new XML document in memory
  xmlRef = document.implementation.createDocument("", "", null);

  // We want to move a part of the DOM from an HTML document to an XML document.
  // importNode is used to clone the nodes we want to process via XSLT - true makes it do a deep clone
  const myNode = document.getElementById("example");
  const clonedNode = xmlRef.importNode(myNode, true);

  // After cloning, we append
  xmlRef.appendChild(clonedNode);

  // Set the sorting parameter in the XSL file
  const sortVal = xsltProcessor.getParameter(null, "myOrder");

  if (sortVal === "" || sortVal === "descending") {
    xsltProcessor.setParameter(null, "myOrder", "ascending");
  } else {
    xsltProcessor.setParameter(null, "myOrder", "descending");
  }

  // Initiate the transformation
  const fragment = xsltProcessor.transformToFragment(xmlRef, document);

  // Clear the contents
  document.getElementById("example").textContent = "";

  myDOM = fragment;

  // Add the new content from the transformation
  document.getElementById("example").appendChild(fragment);
}
```

#### XSLT

```xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

  <xsl:param name="myOrder" />

  <xsl:template match="/">

    <xsl:apply-templates select="/div//div">
      <xsl:sort select="." data-type="number" order="{$myOrder}" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="div">
    <xsl:copy-of select="." />
  </xsl:template>
</xsl:stylesheet>
```

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

| Specification |
| --- |
| DOM Standard # interface-xsltprocessor |

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

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

See also
--------

* XSLT
* What kind of language is XSLT? at IBM developer
* XSLT Tutorial at zvon.org
* XPath Tutorial at zvon.org


XRJointPose - Web APIs

XRJointPose
===========

The **`XRJointPose`** interface is an `XRPose` with additional information about the size of the skeleton joint it represents.

XRPose

XRJointPoseInstance properties
-------------------

`XRJointPose.radius` Read only

The radius (distance from skin) for a joint.

Examples
--------

### Using `XRJointPose` objects

Call `XRFrame.getJointPose()` with an `XRJointSpace` and an `XRReferenceSpace` to get an `XRJointPose` object.

```js
navigator.xr
  .requestSession({ optionalFeatures: ["hand-tracking"] })
  .then(/\* … \*/);

function renderFrame(session, frame) {
  // …

  for (const inputSource of session.inputSources) {
    if (inputSource.hand) {
      const indexFingerTipJoint = inputSource.hand.get("index-finger-tip");
      frame.getJointPose(indexFingerTipJoint, referenceSpace); // XRJointPose
    }
  }
}
```

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

| Specification |
| --- |
| WebXR Hand Input Module - Level 1 # xrjointpose-interface |

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

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

See also
--------

* `XRHand`
* `XRReferenceSpace`
* `XRJointSpace`
* `XRFrame.getJointPose()`


WEBGL_multi_draw extension - Web APIs

WEBGL\_multi\_draw extension
============================

 The **`WEBGL_multi_draw`** extension is part of the
 WebGL API and allows to render more
 than one primitive with a single function call. This can improve a WebGL application's performance
 as it reduces binding costs in the renderer and speeds up GPU thread time with uniform data.

When this extension is enabled:

* New methods that handle multiple lists of arguments in one call are added
 (see method list below).
* The `gl_DrawID` built-in is added to the shading language.

**Note:** This extension is available to both,
 WebGL 1 and
 WebGL 2 contexts.

 In shader code, the directive `#extension GL_ANGLE_multi_draw`
 needs to be called to enable the extension.

This extension enables the `ANGLE_instanced_arrays` extension implicitly.

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

`ext.multiDrawArraysWEBGL()`

 Renders multiple primitives from array data (identical to multiple calls to
 `drawArrays`).

`ext.multiDrawElementsWEBGL()`

 Renders multiple primitives from element array data (identical to multiple calls to
 `drawElements`).

`ext.multiDrawArraysInstancedWEBGL()`

 Renders multiple primitives from array data (identical to multiple calls to
 `drawArraysInstanced`).

`ext.multiDrawElementsInstancedWEBGL()`

 Renders multiple primitives from element array data (identical to multiple calls to
 `drawElementsInstanced`).

Shader extension
----------------

 Note: Although the extension name is named `WEBGL_multi_draw`,
 the extension must be enabled with the `#extension GL_ANGLE_multi_draw`
 directive to use the extension in a shader.

 When this extension is enabled, the `gl_DrawID` built-in can be used
 in shader code. For any `multi*` draw call variant,
 the index of the draw `i` may be read by the vertex shader
 as `gl_DrawID`. For non-`multi*` calls, the value of
 `gl_DrawID` is `0`.

```html
<script type="x-shader/x-vertex">
 #extension GL\_ANGLE\_multi\_draw : require
 void main() {
 gl\_Position = vec4(gl\_DrawID, 0, 0, 1);
 }
</script>
```

Examples
--------

### Enabling the extension

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

```js
let ext = gl.getExtension("WEBGL\_multi\_draw");
```

### Drawing multiple arrays

 Example calls for `ext.multiDrawArraysWEBGL()`
 and `ext.multiDrawArraysInstancedWEBGL()`:

```js
// multiDrawArrays variant
const firsts = new Int32Array(/\* … \*/);
const counts = new Int32Array(/\* … \*/);
ext.multiDrawArraysWEBGL(gl.TRIANGLES, firsts, 0, counts, 0, firsts.length);
```

```js
// multiDrawArraysInstanced variant
const firsts = new Int32Array(/\* … \*/);
const counts = new Int32Array(/\* … \*/);
const instanceCounts = new Int32Array(/\* … \*/);
ext.multiDrawArraysInstancedWEBGL(
  gl.TRIANGLES,
  firsts,
  0,
  counts,
  0,
  instanceCounts,
  0,
  firsts.length,
);
```

### Drawing multiple elements

 Example calls for `ext.multiDrawElementsWEBGL()`
 and `ext.multiDrawElementsInstancedWEBGL()`.

 Assumes that the indices which have been previously uploaded to the
 `ELEMENT_ARRAY_BUFFER` are to be treated as `UNSIGNED_SHORT`.

```js
// multiDrawElements variant
const counts = new Int32Array(/\* … \*/);
const offsets = new Int32Array(/\* … \*/);
ext.multiDrawElementsWEBGL(
  gl.TRIANGLES,
  counts,
  0,
  gl.UNSIGNED\_SHORT,
  offsets,
  0,
  counts.length,
);
```

```js
// multiDrawElementsInstanced variant
const counts = new Int32Array(/\* … \*/);
const offsets = new Int32Array(/\* … \*/);
const instanceCounts = new Int32Array(/\* … \*/);
ext.multiDrawElementsInstancedWEBGL(
  gl.TRIANGLES,
  counts,
  0,
  gl.UNSIGNED\_SHORT,
  offsets,
  0,
  instanceCounts,
  0,
  counts.length,
);
```

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

| Specification |
| --- |
| WebGL WEBGL\_multi\_draw Extension Specification  |

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

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

See also
--------

* `WebGLRenderingContext.drawArrays()`
* `WebGLRenderingContext.drawElements()`
* `ANGLE_instanced_arrays.drawArraysInstancedANGLE()` or
 in WebGL 2: `WebGL2RenderingContext.drawArraysInstanced()`
* `ANGLE_instanced_arrays.drawElementsInstancedANGLE()` or
 in WebGL 2: `WebGL2RenderingContext.drawElementsInstanced()`


XRViewport - Web APIs

XRViewport
==========

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

The WebXR Device API's **`XRViewport`** interface provides properties used to describe the size and position of the current viewport within the `XRWebGLLayer` being used to render the 3D scene.

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

`height` Read only

The height, in pixels, of the viewport.

`width` Read only

The width, in pixels, of the viewport.

`x` Read only

The offset from the origin of the destination graphics surface (typically a `XRWebGLLayer`) to the left edge of the viewport, in pixels.

`y` Read only

The offset from the origin of the viewport to the bottom edge of the viewport; WebGL's coordinate system places (0, 0) at the bottom left corner of the surface.

Usage notes
-----------

Currently, the only type of surface available is the `XRWebGLLayer`. The precise orientation of the coordinate system may vary with other surface types, but in WebGL, the origin (0, 0) is located at the bottom-left corner of the surface. Thus the values specified in an `XRViewport` define a rectangle whose bottom-left corner is at (`x`, `y`) and which extends `width` pixels toward the left and `height` pixels upward.

These values may be passed directly into the `WebGLRenderingContext.viewport()` method:

```js
const xrViewport = xrWebGLLayer.getViewport(xrView);
gl.viewport(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height);
```

Example
-------

This example sets up an animation frame callback using `requestAnimationFrame()`. After initial setup, it iterates over each of the views within the viewer's pose, configuring the viewport as dictated by the `XRWebGLLayer`.

```js
xrSession.requestAnimationFrame((time, xrFrame) => {
  const viewerPose = xrFrame.getViewerPose(xrReferenceSpace);

  gl.bindFramebuffer(xrWebGLLayer.framebuffer);

  for (const xrView of viewerPose.views) {
    const xrViewport = xrWebGLLayer.getViewport(xrView);
    gl.viewport(
      xrViewport.x,
      xrViewport.y,
      xrViewport.width,
      xrViewport.height,
    );

    // Now we can use WebGL to draw into a viewport matching
    // the viewer's needs
  }
});
```

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

| Specification |
| --- |
| WebXR Device API # xrviewport-interface |

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

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


RTCTrackEvent - Web APIs

RTCTrackEvent
=============

The WebRTC API interface **`RTCTrackEvent`** represents the `track` event, which is sent when a new `MediaStreamTrack` is added to an `RTCRtpReceiver` which is part of the `RTCPeerConnection`.

The target is the `RTCPeerConnection` object to which the track is being added.

This event is sent by the WebRTC layer to the website or application, so you will not typically need to instantiate an `RTCTrackEvent` yourself.

Event

RTCTrackEventConstructor
-----------

`RTCTrackEvent()`

Creates and returns a new `RTCTrackEvent` object. You will probably not need to create new track events yourself, since they're typically created by the WebRTC infrastructure and sent to the connection's `ontrack` event handler.

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

*Since `RTCTrackEvent` is based on `Event`, its properties are also available.*

`receiver` Read only

The `RTCRtpReceiver` used by the track that's been added to the `RTCPeerConnection`.

`streams` Read only  Optional

An array of `MediaStream` objects, each representing one of the media streams to which the added `track` belongs. By default, the array is empty, indicating a streamless track.

`track` Read only

The `MediaStreamTrack` which has been added to the connection.

`transceiver` Read only

The `RTCRtpTransceiver` being used by the new track.

Track event types
-----------------

There is only one type of track event.

### `track`

The `track` event is sent to the `RTCPeerConnection` when a new track has been added to the connection. By the time the `track` event is delivered to the `RTCPeerConnection`'s `ontrack` handler, the new media has completed its negotiation for a specific `RTCRtpReceiver` (which is specified by the event's `receiver` property).

In addition, the `MediaStreamTrack` specified by the receiver's `track` is the same one specified by the event's `track`, and the track has been added to any associated remote `MediaStream` objects.

You can add a `track` event listener to be notified when the new track is available so that you can, for example, attach its media to a `<video>` element, using either `RTCPeerConnection.addEventListener()` or the `ontrack` event handler property.

**Note:** It may be helpful to keep in mind that you receive the `track` event when a new inbound track has been added to your connection, and you call `addTrack()` to add a track to the far end of the connection, thereby triggering a `track` event on the remote peer.

Example
-------

This simple example creates an event listener for the `track` event which sets the `srcObject` of the `<video>` element with the ID `videobox` to the first stream in the list passed in the event's `streams` array.

```js
peerConnection.addEventListener(
  "track",
  (e) => {
    let videoElement = document.getElementById("videobox");
    videoElement.srcObject = e.streams[0];
  },
  false,
);
```

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

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

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

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


IntersectionObserverEntry - Web APIs

IntersectionObserverEntry
=========================

The **`IntersectionObserverEntry`** interface of the Intersection Observer API describes the intersection between the target element and its root container at a specific moment of transition.

Instances of `IntersectionObserverEntry` are delivered to an `IntersectionObserver` callback in its `entries` parameter; otherwise, these objects can only be obtained by calling `IntersectionObserver.takeRecords()`.

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

`IntersectionObserverEntry.boundingClientRect` Read only

Returns the bounds rectangle of the target element as a `DOMRectReadOnly`. The bounds are computed as described in the documentation for `Element.getBoundingClientRect()`.

`IntersectionObserverEntry.intersectionRatio` Read only

Returns the ratio of the `intersectionRect` to the `boundingClientRect`.

`IntersectionObserverEntry.intersectionRect` Read only

Returns a `DOMRectReadOnly` representing the target's visible area.

`IntersectionObserverEntry.isIntersecting` Read only

A Boolean value which is `true` if the target element intersects with the intersection observer's root. If this is `true`, then, the `IntersectionObserverEntry` describes a transition into a state of intersection; if it's `false`, then you know the transition is from intersecting to not-intersecting.

`IntersectionObserverEntry.rootBounds` Read only

Returns a `DOMRectReadOnly` for the intersection observer's root.

`IntersectionObserverEntry.target` Read only

The `Element` whose intersection with the root changed.

`IntersectionObserverEntry.time` Read only

A `DOMHighResTimeStamp` indicating the time at which the intersection was recorded, relative to the `IntersectionObserver`'s time origin.

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

*This interface has no methods.*

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

| Specification |
| --- |
| Intersection Observer # intersection-observer-entry |

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

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


TextMetrics - Web APIs

TextMetrics
===========

The **`TextMetrics`** interface represents the dimensions of a piece of text in the canvas; a `TextMetrics` instance can be retrieved using the `CanvasRenderingContext2D.measureText()` method.

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

`TextMetrics.width` Read only

Returns the width of a segment of inline text in CSS pixels. It takes into account the current font of the context.

`TextMetrics.actualBoundingBoxLeft` Read only

Distance parallel to the baseline from the alignment point given by the `CanvasRenderingContext2D.textAlign` property to the left side of the bounding rectangle of the given text, in CSS pixels; positive numbers indicating a distance going left from the given alignment point.

`TextMetrics.actualBoundingBoxRight` Read only

Returns the distance from the alignment point given by the `CanvasRenderingContext2D.textAlign` property to the right side of the bounding rectangle of the given text, in CSS pixels. The distance is measured parallel to the baseline.

`TextMetrics.fontBoundingBoxAscent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the top of the highest bounding rectangle of all the fonts used to render the text, in CSS pixels.

`TextMetrics.fontBoundingBoxDescent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the bottom of the bounding rectangle of all the fonts used to render the text, in CSS pixels.

`TextMetrics.actualBoundingBoxAscent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the top of the bounding rectangle used to render the text, in CSS pixels.

`TextMetrics.actualBoundingBoxDescent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` attribute to the bottom of the bounding rectangle used to render the text, in CSS pixels.

`TextMetrics.emHeightAscent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the top of the *em* square in the line box, in CSS pixels.

`TextMetrics.emHeightDescent` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the bottom of the *em* square in the line box, in CSS pixels.

`TextMetrics.hangingBaseline` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the hanging baseline of the line box, in CSS pixels.

`TextMetrics.alphabeticBaseline` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the alphabetic baseline of the line box, in CSS pixels.

`TextMetrics.ideographicBaseline` Read only

Returns the distance from the horizontal line indicated by the `CanvasRenderingContext2D.textBaseline` property to the ideographic baseline of the line box, in CSS pixels.

Examples
--------

### Baselines illustrated

This example demonstrates the baselines the `TextMetrics` object holds. The default baseline is the `alphabeticBaseline`. See also the `CanvasRenderingContext2D.textBaseline` property.

#### HTML

```html
<canvas id="canvas" width="550" height="500"></canvas>
```

#### JavaScript

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

const baselinesAboveAlphabetic = [
  "fontBoundingBoxAscent",
  "actualBoundingBoxAscent",
  "emHeightAscent",
  "hangingBaseline",
];
const baselinesBelowAlphabetic = [
  "ideographicBaseline",
  "emHeightDescent",
  "actualBoundingBoxDescent",
  "fontBoundingBoxDescent",
];
const baselines = [...baselinesAboveAlphabetic, ...baselinesBelowAlphabetic];
ctx.font = "25px serif";
ctx.strokeStyle = "red";

baselines.forEach((baseline, index) => {
  const text = `Abcdefghijklmnop (${baseline})`;
  const textMetrics = ctx.measureText(text);
  const y = 50 + index \* 50;
  ctx.beginPath();
  ctx.fillText(text, 0, y);

  const baselineMetricValue = textMetrics[baseline];
  if (baselineMetricValue === undefined) {
    return;
  }

  const lineY = baselinesBelowAlphabetic.includes(baseline)
    ? y + Math.abs(baselineMetricValue)
    : y - Math.abs(baselineMetricValue);
  ctx.moveTo(0, lineY);
  ctx.lineTo(550, lineY);
  ctx.stroke();
});
```

#### Result

### Measuring text width

When measuring the x-direction of a piece of text, the sum of `actualBoundingBoxLeft` and `actualBoundingBoxRight` can be wider than the width of the inline box (`width`), due to slanted/italic fonts where characters overhang their advance width.

It can therefore be useful to use the sum of `actualBoundingBoxLeft` and `actualBoundingBoxRight` as a more accurate way to get the absolute text width:

```js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const text = "Abcdefghijklmnop";
ctx.font = "italic 50px serif";
const textMetrics = ctx.measureText(text);

console.log(textMetrics.width);
// 459.8833312988281

console.log(
  textMetrics.actualBoundingBoxRight + textMetrics.actualBoundingBoxLeft,
);
// 462.8833333333333
```

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

| Specification |
| --- |
| HTML Standard # textmetrics |

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

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

See also
--------

* Creator method in `CanvasRenderingContext2D`
* The `<canvas>` element and its associated interface, `HTMLCanvasElement`


SharedStorageRunOperation - Web APIs

SharedStorageRunOperation
=========================

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

The **`SharedStorageRunOperation`** interface of the Shared Storage API represents a Run output gate operation.

SharedStorageOperation

SharedStorageRunOperationInstance methods
----------------

`run()`
Experimental

Defines the structure to which the `run()` method defined inside a Run output gate operation should conform.

Examples
--------

In this example, a class called `ReachMeasurementOperation` is defined in a worklet and is registered using `SharedStorageWorkletGlobalScope.register()` with the name `reach-measurement`. `SharedStorageRunOperation` defines the structure to which this class must conform, essentially defining the parameters required for the `run()` method. Other than this requirement, the functionality of the class can be defined flexibly.

```js
// reach-measurement-worklet.js
const SCALE\_FACTOR = 65536;

function convertContentIdToBucket(contentId) {
  return BigInt(contentId);
}

class ReachMeasurementOperation {
  async run(data) {
    const { contentId } = data;

    // Read from Shared Storage
    const key = "has-reported-content";
    const hasReportedContent = (await this.sharedStorage.get(key)) === "true";

    // Do not report if a report has been sent already
    if (hasReportedContent) {
      return;
    }

    // Generate the aggregation key and the aggregatable value
    const bucket = convertContentIdToBucket(contentId);
    const value = 1 \* SCALE\_FACTOR;

    // Send an aggregatable report via the Private Aggregation API
    privateAggregation.sendHistogramReport({ bucket, value });

    // Set the report submission status flag
    await this.sharedStorage.set(key, true);
  }
}

// Register the operation
register("reach-measurement", ReachMeasurementOperation);
```

**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.

In the main browsing context, the `reach-measurement` operation is invoked using the `WindowSharedStorage.run()` method:

```js
async function measureUniqueReach() {
  // Load the Shared Storage worklet
  await window.sharedStorage.worklet.addModule("reach-measurement-worklet.js");

  // Run the reach measurement operation
  await window.sharedStorage.run("reach-measurement", {
    data: { contentId: "1234" },
  });
}

measureUniqueReach();
```

For more details about this example, see Unique reach measurement. See Shared Storage API for more examples.

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

| Specification |
| --- |
| Shared Storage API # sharedstoragerunoperation |

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

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

See also
--------

* Shared Storage API