MouseEvent: movementY property - Web APIs

MouseEvent: movementY property
==============================

 The **`movementY`** read-only property of the `MouseEvent` interface provides the difference in the Y coordinate of the mouse pointer between the given event and the previous `mousemove` event.
 In other words, the value of the property is computed like this: `currentEvent.movementY = currentEvent.screenY - previousEvent.screenY`.

**Warning:** Browsers use different units for `movementY` and `screenY` than what the specification defines. Depending on the browser and operating system, the `movementY` units may be a physical pixel, a logical pixel, or a CSS pixel. You may want to avoid the movement properties, and instead calculate the delta between the current client values (`screenX`, `screenY`) and the previous client values.

Value
-----

A number. Always zero on any `MouseEvent` other than `mousemove`.

Examples
--------

This example logs the amount of mouse movement using `movementX` and `movementY`.

### HTML

```html
<p id="log">Move your mouse around.</p>
```

### JavaScript

```js
function logMovement(event) {
  log.innerText = `movement: ${event.movementX}, ${event.movementY}\n${log.innerText}`;
}

const log = document.getElementById("log");
document.addEventListener("mousemove", logMovement);
```

### Result

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

| Specification |
| --- |
| Pointer Lock 2.0 # dom-mouseevent-movementy |

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

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

See also
--------

* `MouseEvent.movementX`
* `MouseEvent`
* Pointer Lock


MouseEvent: webkitForce property - Web APIs

MouseEvent: webkitForce property
================================

**Non-standard:** This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

**`MouseEvent.webkitForce`** is a proprietary, WebKit-specific numeric property whose value represents the amount of pressure that is being applied on the touchpad or touchscreen.

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

*Not part of any specification.* Apple has a description at the Mac Developer Library.

See also
--------

* `MouseEvent.WEBKIT_FORCE_AT_MOUSE_DOWN`
* `MouseEvent.WEBKIT_FORCE_AT_FORCE_MOUSE_DOWN`


MouseEvent: x property - Web APIs

MouseEvent: x property
======================

The **`MouseEvent.x`** property is an alias for the `MouseEvent.clientX` property.

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

| Specification |
| --- |
| CSSOM View Module # dom-mouseevent-x |

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

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


MouseEvent: screenX property - Web APIs

MouseEvent: screenX property
============================

The **`screenX`** read-only property of the `MouseEvent` interface provides the horizontal coordinate (offset) of the mouse pointer in screen coordinates.

**Note:** In a multiscreen environment, screens aligned horizontally will be treated as a single device, and so the range of the `screenX` value will increase to the combined width of the screens.

Value
-----

A `double` floating point value.

Early versions of the spec defined this as an integer referring to the number of pixels.

Examples
--------

This example displays your mouse's coordinates whenever you trigger the `mousemove` event.

### HTML

```html
<p>Move your mouse to see its position.</p>
<p id="screen-log"></p>
```

### JavaScript

```js
let screenLog = document.querySelector("#screen-log");
document.addEventListener("mousemove", logKey);

function logKey(e) {
  screenLog.innerText = `
 Screen X/Y: ${e.screenX}, ${e.screenY}
 Client X/Y: ${e.clientX}, ${e.clientY}`;
}
```

### Result

### Routing an event

When you trap events on the window, document, or other roomy elements, you can get the coordinates of that event (e.g., a click) and route it properly, as the following example demonstrates:

```js
function checkClickMap(e) {
  if (e.screenX < 50) doRedButton();
  if (50 <= e.screenX && e.screenX < 100) doYellowButton();
  if (e.screenX >= 100) doRedButton();
}
```

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

| Specification |
| --- |
| UI Events # dom-mouseevent-screenx |

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

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

See also
--------

* `MouseEvent`
* `screenY`
* `clientX` / `clientY`
* Coordinate systems


MouseEvent: y property - Web APIs

MouseEvent: y property
======================

The **`MouseEvent.y`** property is an alias for the `MouseEvent.clientY` property.

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

| Specification |
| --- |
| CSSOM View Module # dom-mouseevent-y |

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

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


MouseEvent: screenY property - Web APIs

MouseEvent: screenY property
============================

The **`screenY`** read-only property of the `MouseEvent` interface provides the vertical coordinate (offset) of the mouse pointer in screen coordinates.

Value
-----

A `double` floating point value.

Early versions of the spec defined this as an integer referring to the number of pixels.

Examples
--------

This example displays your mouse's coordinates whenever you trigger the `mousemove` event.

### HTML

```html
<p>Move your mouse to see its position.</p>
<p id="screen-log"></p>
```

### JavaScript

```js
let screenLog = document.querySelector("#screen-log");
document.addEventListener("mousemove", logKey);

function logKey(e) {
  screenLog.innerText = `
 Screen X/Y: ${e.screenX}, ${e.screenY}
 Client X/Y: ${e.clientX}, ${e.clientY}`;
}
```

### Result

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

| Specification |
| --- |
| UI Events # dom-mouseevent-screeny |

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

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

See also
--------

* `MouseEvent`
* `screenX`
* `clientX` / `clientY`
* Coordinate systems


MouseEvent: clientY property - Web APIs

MouseEvent: clientY property
============================

The **`clientY`** read-only property of the `MouseEvent` interface provides the vertical coordinate within the application's viewport at which the event occurred (as opposed to the coordinate within the page).

For example, clicking on the top edge of the viewport will always result in a mouse event with a `clientY` value of `0`, regardless of whether the page is scrolled vertically.

Value
-----

A `double` floating point value.

Examples
--------

This example displays your mouse's coordinates whenever you trigger the `mousemove` event.

### HTML

```html
<p>Move your mouse to see its position.</p>
<p id="screen-log"></p>
```

### JavaScript

```js
let screenLog = document.querySelector("#screen-log");
document.addEventListener("mousemove", logKey);

function logKey(e) {
  screenLog.innerText = `
 Screen X/Y: ${e.screenX}, ${e.screenY}
 Client X/Y: ${e.clientX}, ${e.clientY}`;
}
```

### Result

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

| Specification |
| --- |
| UI Events # dom-mouseevent-clienty |

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

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

See also
--------

* `MouseEvent`
* `clientX`
* `screenX` / `screenY`
* Coordinate systems


MouseEvent: MouseEvent() constructor - Web APIs

MouseEvent: MouseEvent() constructor
====================================

The **`MouseEvent()`** constructor creates a new `MouseEvent` object.

Syntax
------

```js
new MouseEvent(type)
new MouseEvent(type, options)
```

### Parameters

`type`

 A string with the name of the event.
 It is case-sensitive and browsers set it to `dblclick`, `mousedown`, `mouseenter`, `mouseleave`, `mousemove`, `mouseout`, `mouseover`, or `mouseup`.

`options` Optional

An object that, *in addition of the properties defined in `UIEvent()`*, can have the following properties:

`screenX` Optional

 A number, defaulting to `0`, that is the horizontal position of the mouse event on the user's screen;
 setting this value doesn't move the mouse pointer.

`screenY` Optional

 A number, defaulting to `0`, that is the vertical position of the mouse event on the user's screen;
 setting this value doesn't move the mouse pointer.

`clientX` Optional

 A number, defaulting to `0`, that is the horizontal position of the mouse event on the client window of user's screen;
 setting this value doesn't move the mouse pointer.

`clientY` Optional

 A number, defaulting to `0`, that is the vertical position of the mouse event on the client window of the user's screen;
 setting this value doesn't move the mouse pointer.

`ctrlKey` Optional

A boolean value indicating if the `ctrl` key was simultaneously pressed. It defaults to `false`.

`shiftKey` Optional

A boolean value indicating if the `shift` key was simultaneously pressed. It defaults to `false`.

`altKey` Optional

A boolean value indicating if the `alt` key was simultaneously pressed. It defaults to `false`.

`metaKey` Optional

A boolean value indicating if the `meta` key was simultaneously pressed. It defaults to `false`.

`button` Optional

A number, defaulting to `0`, that describes which button is pressed during events related to the press or release of a button:

| Value | Meaning |
| --- | --- |
| `0` | Main button pressed (usually the left button) or un-initialized |
| `1` | Auxiliary button pressed (usually the middle button) |
| `2` | Secondary button pressed (usually the right button) |

`buttons` Optional

A number, defaulting to `0`, that describes which buttons are pressed when the event is launched:

| Bit-field value | Meaning |
| --- | --- |
| `0` | No button pressed |
| `1` | Main button pressed (usually the left button) |
| `2` | Secondary button pressed (usually the right button) |
| `4` | Auxiliary button pressed (usually the middle button) |

`relatedTarget` Optional

 An `EventTarget`, defaulting to `null` that is the element just left
 (in case of a `mouseenter` or `mouseover`)
 or is entering (in case of a `mouseout` or `mouseleave`).

`region`
Non-standard
 Optional

 A string, defaulting to `null`, that is the ID of the hit region affected by the event.
 The absence of any affected hit region is represented with the `null` value.

 In some implementations, passing anything other than a number for the screen and
 client fields will throw a `TypeError`.

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

| Specification |
| --- |
| UI Events # dom-mouseevent-mouseevent |

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

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

See also
--------

* `MouseEvent`, the interface of the objects it constructs.


MouseEvent: movementX property - Web APIs

MouseEvent: movementX property
==============================

 The **`movementX`** read-only property of the `MouseEvent` interface provides the difference in the X coordinate of the mouse pointer between the given event and the previous `mousemove` event.
 In other words, the value of the property is computed like this: `currentEvent.movementX = currentEvent.screenX - previousEvent.screenX`.

**Warning:** Browsers use different units for `movementX` and `screenX` than what the specification defines. Depending on the browser and operating system, the `movementX` units may be a physical pixel, a logical pixel, or a CSS pixel. You may want to avoid the movement properties, and instead calculate the delta between the current client values (`screenX`, `screenY`) and the previous client values.

Value
-----

A number. Always zero on any `MouseEvent` other than `mousemove`.

Examples
--------

This example logs the amount of mouse movement using `movementX` and `movementY`.

### HTML

```html
<p id="log">Move your mouse around.</p>
```

### JavaScript

```js
function logMovement(event) {
  log.insertAdjacentHTML(
    "afterbegin",
    `movement: ${event.movementX}, ${event.movementY}<br>`,
  );
  while (log.childNodes.length > 128) log.lastChild.remove();
}

const log = document.getElementById("log");
document.addEventListener("mousemove", logMovement);
```

### Result

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

| Specification |
| --- |
| Pointer Lock 2.0 # dom-mouseevent-movementx |

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

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

See also
--------

* `MouseEvent.movementY`
* `MouseEvent`
* Pointer Lock


MouseEvent: getModifierState() method - Web APIs

MouseEvent: getModifierState() method
=====================================

The **`MouseEvent.getModifierState()`** method returns the current state of the specified modifier key: `true` if the modifier is active (i.e., the modifier key is pressed or locked), otherwise, `false`.

See `KeyboardEvent.getModifierState()` for details.

Syntax
------

```js
getModifierState(key)
```

### Parameters

`key`

 A modifier key value.
 The value must be one of the `KeyboardEvent.key` values which represent modifier keys or `"Accel"`
Deprecated
.
 This is case-sensitive.

### Return value

A boolean value.

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

| Specification |
| --- |
| UI Events # dom-mouseevent-getmodifierstate |

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

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

See also
--------

* The `MouseEvent` this method belongs to.
* `KeyboardEvent.getModifierState`


HTMLCollection: item() method - Web APIs

HTMLCollection: item() method
=============================

 The `HTMLCollection` method `item()`
 returns the element located at the specified offset into the collection.

**Note:** Because the contents of an `HTMLCollection` are
 live, changes to the underlying DOM can and will cause the position of individual
 elements in the collection to change, so the index value will not necessarily remain
 constant for a given element.

Syntax
------

```js
item(index)
```

### Parameters

`index`

 The position of the `Element` to be returned. Elements appear in an
 `HTMLCollection` in the same order in which they appear in the document's
 source.

### Return value

 The `Element` at the specified index, or `null` if
 `index` is less than zero or greater than or equal to the length property.

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

 The `item()` method returns a numbered element from an
 `HTMLCollection`. In JavaScript, it is easier to treat the
 `HTMLCollection` as an array and to index it using array notation. See the
 example below.

Examples
--------

```js
const images = document.images; // This is an HTMLCollection
const img0 = images.item(0); // You can use the item() method this way
const img1 = images[1]; // But this notation is easier and more common
```

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

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

See also
--------

* `NodeList.item()`


HTMLCollection: namedItem() method - Web APIs

HTMLCollection: namedItem() method
==================================

 The **`namedItem()`** method of the `HTMLCollection` interface returns
 the first `Element` in the collection whose `id` or `name` attribute match the specified name, or `null` if no element matches.

In JavaScript, using the array bracket syntax with a `String`, like `collection["value"]` is equivalent to `collection.namedItem("value")`.

Syntax
------

```js
namedItem(key)
```

### Parameters

* `key` is a string representing the value of the `id` or `name` attribute of the element we are looking for.
### Return value

* `item` is the first `Element` in the `HTMLCollection` matching the *key*, or `null`, if there are none.
Example
-------

### HTML

```html
<div id="personal">
  <span name="title">Dr.</span>
  <span name="firstname">Carina</span>
  <span name="lastname">Anand</span>
  <span id="degree">(MD)</span>
</div>
```

### JavaScript

```js
const container = document.getElementById("personal");

// Returns the HTMLSpanElement with the name "title" if no such element exists null is returned
const titleSpan = container.children.namedItem("title");

// The following variants return undefined instead of null if there's no element with a matching name or id
const firstnameSpan = container.children["firstname"];
const lastnameSpan = container.children.lastname;

// Returns the span element with the id "degree"
const degreeSpan = container.children.namedItem("degree");

const output = document.createElement("div");
output.textContent = `Result: ${titleSpan.textContent} ${firstnameSpan.textContent} ${lastnameSpan.textContent} ${degreeSpan.textContent}`;

container.insertAdjacentElement("afterend", output);
```

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

| Specification |
| --- |
| DOM Standard # dom-htmlcollection-nameditem-key |

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

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


HTMLCollection: length property - Web APIs

HTMLCollection: length property
===============================

 The **`HTMLCollection.length`** property returns the number of
 items in a `HTMLCollection`.

Value
-----

An integer value representing the number of items in a `HTMLCollection`.

Examples
--------

 The `length` property is often useful in DOM programming. It's often used to
 test the length of a list, to see if it exists at all. It's also commonly used as the
 iterator in a `for` loop, as in this example.

```js
// All the elements with the class ".test" in the document
const items = document.getElementsByClassName("test");

// For each test item in the list,
// append the entire element as a string of HTML
let gross = "";
for (let i = 0; i < items.length; i++) {
  gross += items[i].innerHTML;
}

// gross is now all the HTML for the test elements
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-htmlcollection-length① |

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

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


ReadableStreamBYOBRequest: view property - Web APIs

ReadableStreamBYOBRequest: view property
========================================

The **`view`** getter property of the `ReadableStreamBYOBRequest` interface returns the current view.

Value
-----

A typed array representing the destination region to which the controller can write generated data.

`null` if the request has already been responded to, by calling `ReadableStreamBYOBRequest.respond()` or `ReadableStreamBYOBRequest.respondWithNewView()`.

Examples
--------

See the examples in `ReadableStreamBYOBRequest`.

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

| Specification |
| --- |
| Streams Standard # ref-for-rs-byob-request-view① |

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

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

See also
--------

* Using readable byte stream


ReadableStreamBYOBRequest: respondWithNewView() method - Web APIs

ReadableStreamBYOBRequest: respondWithNewView() method
======================================================

The **`respondWithNewView()`** method of the `ReadableStreamBYOBRequest` interface specifies a new view that the consumer of the associated readable byte stream should write to instead of `ReadableStreamBYOBRequest.view`.

 The new view must be a `TypedArray` or a `DataView` that provides a view onto the same backing memory region as `ReadableStreamBYOBRequest.view`.
 After this method is called, the view that was passed into the method will be transferred and no longer modifiable.

 The method is intended for use cases where an underlying byte source needs to transfer a `byobRequest.view` internally before finishing its response.
 For example, the source may transfer the BYOB view to a separate worker thread, and wait for the worker to transfer it back once it has been filled.

Syntax
------

```js
respondWithNewView(view)
```

### Parameters

`view`

A `TypedArray` or a `DataView` that the consumer of the associated readable byte stream should write to instead of `ReadableStreamBYOBRequest.view`.

 This must be a view onto the same backing memory region as `ReadableStreamBYOBRequest.view` and occupy the same or less memory.
 Specifically, it must be either the view's buffer or a transferred version, must have the same `byteOffset`, and a `byteLength` (number of bytes written) that is less than or equal to that of the view.

### Return value

None (`undefined`).

### Exceptions

`TypeError`

 Thrown if the source object is not a `ReadableStreamBYOBRequest`, or there is no associated controller, or the associated internal array buffer is non-existent or detached.
 It may also be thrown if the `view` is zero-length when there is an active reader, or non-zero when called on a closed stream.

`RangeError`

 Thrown if the new `view` does not match the backing memory region of `ReadableStreamBYOBRequest.view`.
 For example, it is not the same buffer (or a transferred version), has a different `byteOffset`, or is larger than the memory available to the backing view.

Examples
--------

The view to be transferred must be of the same type as `ReadableStreamBYOBRequest.view`, have the same underlying buffer and byte offset, and be the same or smaller byteLength.

For example, we might define the view and respond as shown below:

```js
const v = controller.byobRequest.view;
bytesRead = socket.readInto(v.buffer, v.byteOffset, v.byteLength);
byobRequest.respondWithNewView(
  byobRequest.view.subarray(v.byteOffset, bytesRead),
);
```

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

| Specification |
| --- |
| Streams Standard # ref-for-rs-byob-request-respond-with-new-view① |

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

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

See also
--------

* Using readable byte stream


ReadableStreamBYOBRequest: respond() method - Web APIs

ReadableStreamBYOBRequest: respond() method
===========================================

The **`respond()`** method of the `ReadableStreamBYOBRequest` interface is used to signal to the associated readable byte stream that the specified number of bytes were written into the `ReadableStreamBYOBRequest.view`.

After this method is called, the `view` will be transferred and no longer modifiable.

Syntax
------

```js
respond(bytesWritten)
```

### Parameters

`bytesWritten`

The number of bytes written into `ReadableStreamBYOBRequest.view`.

### Return value

None (`undefined`).

### Exceptions

`TypeError`

The request does not have an associated `ReadableByteStreamController` or the view buffer is not detached/cannot be transferred into.

Examples
--------

The code below is taken from the live examples in Using readable byte stream.

 The method is called by an underlying byte source as part of making a zero-copy transfer of data to fulfill a pending read request from a consumer.
 The underlying source first writes data into the `ReadableStreamBYOBRequest.view` and then calls this `respond()` method to indicate *how* much data was copied into the buffer, and cause the data to be transferred to the reader.

The code below shows this case using a hypothetical `readInto()` method to copy data into the view:

```js
const v = controller.byobRequest.view;
bytesRead = socket.readInto(v.buffer, v.byteOffset, v.byteLength);
controller.byobRequest.respond(bytesRead);
```

After the operation the `byobRequest.view` is detached and the request should be discarded.

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

| Specification |
| --- |
| Streams Standard # ref-for-rs-byob-request-respond① |

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

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

See also
--------

* Using readable byte stream


XRReferenceSpace: getOffsetReferenceSpace() method - Web APIs

XRReferenceSpace: getOffsetReferenceSpace() method
==================================================

 The `XRReferenceSpace`
 interface's **`getOffsetReferenceSpace()`** method returns a
 new reference space object which describes the relative difference in position between
 the object on which the method is called and a given point in 3D space. The
 object returned by `getOffsetReferenceSpace()` is an
 `XRReferenceSpace` if called on an `XRReferenceSpace`, or an
 `XRBoundedReferenceSpace` if called on an object of that type.

 In other words, when you have an object in 3D space and need to position another object
 relative to that one, you can call `getOffsetReferenceSpace()`, passing into
 it the position and orientation you want the second object to have
 *relative to the position and orientation of the object on which you call `getOffsetReferenceSpace()`*.

 Then, when drawing the scene, you can use the offset reference space to not only
 position objects relative to one another, but to apply the needed transforms to render
 objects properly based upon the viewer's position. This is demonstrated in the example
 Implementing rotation based on non-XR inputs, which demonstrates a way to
 use this method to let the user use their mouse to pitch and yaw their viewing angle.

Syntax
------

```js
getOffsetReferenceSpace(originOffset)
```

### Parameters

`originOffset`

 An `XRRigidTransform` specifying the offset to the origin of the new
 reference space. These values are added to the position and orientation of the current
 reference space and then the result is used as the position and orientation of the
 newly created `XRReferenceSpace`.

### Return value

 A new `XRReferenceSpace` object describing a reference space with the same
 native origin as the reference space on which the method was called, but with an origin
 offset indicating the distance from the object to the point given
 by `originOffset`.

 If the object on which you call this method is an
 `XRBoundedReferenceSpace`, the returned object is one as well. The
 `boundsGeometry` of the new
 reference space is set to the original object's `boundsGeometry` with each of
 its points multiplied by the inverse of `originOffset`.

Examples
--------

Below are some examples showing how to use `getOffsetReferenceSpace()`.

### Teleporting or setting the position of the viewer

 Upon first creating a scene, you may need to set the user's position within the 3D
 world. You can do that using `getOffsetReferenceSpace()`.

```js
xrSession.requestReferenceSpace("local").then((refSpace) => {
  xrReferenceSpace = refSpace;
  xrReferenceSpace = xrReferenceSpace.getOffsetReferenceSpace(
    new XRRigidTransform(startPosition, { x: 0, y: 0, z: 1.0, w: 1.0 }),
  );
  xrSession.requestAnimationFrame(drawFrame);
});
```

 In this code, we obtain a local reference space, then
 use `getOffsetReferenceSpace()` to create a new space whose origin is
 adjusted to a position given by `startPosition` and whose orientation is
 looking directly along the Z axis. Then the first animation frame is requested using
 `XRSession`'s `requestAnimationFrame()`.

### Implementing rotation based on non-XR inputs

 The input controls supported directly by WebXR are all dedicated VR or AR input
 devices. In order to use mouse, keyboard, or other input devices to move or otherwise
 transform objects in the 3D space—or to allow the user to move through the space—you'll
 need to write some code to read the inputs and move perform the movements.

 This is another good use case for `getOffsetReferenceSpace()`. In this
 example, we'll show code that lets the user look around by right-clicking and moving the
 mouse to change the viewing angle.

 First, we add an event handler for `mousemove`
 events, which calls our code to perform the rotation if the right mouse button is down.
 Note also that we set `oncontextmenu` up to be
 ignored by calling `preventDefault()` on those
 events. This prevents the right-clicks from causing the context menu from appearing in
 the browser.

```js
canvas.oncontextmenu = (event) => {
  event.preventDefault();
};
canvas.addEventListener("mousemove", (event) => {
  if (event.buttons & 2) {
    rotateViewBy(event.movementX, event.movementY);
  }
});
```

 Next, the `rotateViewBy()` function, which updates the mouse look
 direction's yaw and pitch based on the mouse delta values from
 the `mousemove` event. The pitch is restricted so that you can't look beyond
 straight up and straight down. Each time this is called, the new offsets are used to
 update the current values of `mousePitch` and `mouseYaw`.

```js
let mouseYaw = 0.0;
let mousePitch = 0.0;
const inverseOrientation = quat.create();
const MOUSE\_SPEED = 0.003;

function rotateViewBy(dx, dy) {
  mouseYaw += dx \* MOUSE\_SPEED;
  mousePitch += dy \* MOUSE\_SPEED;

  if (mousePitch < -Math.PI \* 0.5) {
    mousePitch = -Math.PI \* 0.5;
  } else if (mousePitch > Math.PI \* 0.5) {
    mousePitch = Math.PI \* 0.5;
  }
}
```

 Finally, we need code that actually applies the computed yaw and pitch to the viewer's
 orientation. This function, `applyMouseMovement()`, handles that:

```js
function applyMouseMovement(refSpace) {
  if (!mouseYaw && !mousePitch) {
    return refSpace;
  }

  quat.identity(inverseOrientation);
  quat.rotateX(inverseOrientation, inverseOrientation, -mousePitch);
  quat.rotateY(inverseOrientation, inverseOrientation, -mouseYaw);

  let newTransform = new XRRigidTransform(
    { x: 0, y: 0, z: 0 },
    {
      x: inverseOrientation[0],
      y: inverseOrientation[1],
      z: inverseOrientation[2],
      w: inverseOrientation[3],
    },
  );

  return refSpace.getOffsetReferenceSpace(newTransform);
}
```

 This function creates an inverse orientation matrix—used to orient the viewer—from the
 current pitch and yaw values, then uses that matrix as the source of the orientation
 when calling `new XRRigidTransform()`.
 The new `XRRigidTransform`'s reference space is then fetched and returned
 to the caller.

 This new reference space is one in which the viewer's position is unchanged, but their
 orientation has been altered based on the pitch and yaw values generated from the
 accumulated mouse inputs. `applyMouseMovement()` should be called when
 drawing a frame, immediately before fetching the viewer's pose using
 `getViewerPose()`, and the rendering should be
 performed in this reference space.

You can see code similar to this in use in our broader WebXR tutorial article called Movement, orientation, and motion. In particular, check out the section called Starting up the WebXR session.

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

| Specification |
| --- |
| WebXR Device API # dom-xrreferencespace-getoffsetreferencespace |

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

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


XRReferenceSpace: reset event - Web APIs

XRReferenceSpace: reset event
=============================

The **`reset`** event is sent to an `XRReferenceSpace` object when a discontinuity is detected in either the native origin or the effective origin, causing a jump in the position or orientation of objects oriented using the reference space. This is common when the user calibrates or recalibrates an XR device, or if the device automatically changes its origin after losing tracking of the user, then re-gaining it.

In the case of `XRBoundedReferenceSpace` objects, the `reset` event can also be fired when the `boundsGeometry` changes.

In either case, the event is sent before any WebXR animation frames which make use of the new origin are executed.

This event is not cancelable.

Syntax
------

Use the event name in methods like `addEventListener()`, or set an event handler property.

```js
addEventListener("reset", (event) => {});

onreset = (event) => {};
```

Event type
----------

An `XRReferenceSpaceEvent`. Inherits from `Event`.

Event properties
----------------

*In addition to the properties listed below, properties from the parent interface, `Event`, are available.*

`referenceSpace` Read only

An `XRReferenceSpace` indicating the reference space that generated the event.

`transform` Read only

An `XRRigidTransform` object indicating the position and orientation of the specified `referenceSpace` object's native origin after the event, defined relative to the coordinate system before the event.

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

The `reset` event indicates that the coordinate system has been reset or reconfigured by changing the reference space's origin, moving and rotating it as indicated by the event's `transform` property. The event is sent before any animation frame callbacks are executed to render the pending frame, to ensure that those callbacks have the updated coordinate system available.

There are a number of reasons why a reset might occur. Most common among them are the following:

* The user has manually reset the coordinate system, such as by requesting that the headset recalibrate itself to ensure that the facing direction and hand controllers are synchronized with the user's actual position and facing. This is primarily an issue for `local` or `local-floor` reference spaces.
* For a `bounded-floor` reference space, the coordinate system can be reset if the user exits the boundaries of the reference space and enters a new one (such as by crossing from one level to another in a game, where each level is its own map with its own coordinate system).
* The tracking system has temporarily lost the user, then regained them, but not until after they had moved enough to leave the immediate vicinity of the last-known position. Primarily an issue for `unbounded` reference spaces.
* The user is in an `unbounded` reference space and has moved far enough from the starting position (the reference space's origin) that floating-point or other forms of error or drift are problematic. The coordinate system is thus reset with its new origin at or near the user's current position.
* The WebXR infrastructure or hardware drivers detected that the device had temporarily lost tracking, causing the hardware and software to be out of sync on position and orientation.

**Note:** A `reset` event will *not* occur if the reference space is able to regain tracking of its previous origin, since that means the origin has not been forced to be relocated. This event is only fired when the origin has to be relocated to recover from the tracking loss.

### Manual resets

If you've spent any time using a VR headset, you've had times when you've started it up and although you're facing straight ahead, the headset thinks you're looking at the sky or the floor; or times when you point the hand controller straight forward, but it thinks you're pointing it up and to the right somewhere. When that happens, you typically hold down a button somewhere and it causes the world to resynchronize to the device's current orientation. That works by sending a `reset` event to the reference space or reference spaces that are based on the headset's orientation.

### Handling discontinuities

You can handle jumps in the viewer's position by watching the Boolean `XRPose` property `emulatedPosition`. If a jump in the viewer's position coincides with `emulatedPosition` toggling from `true` to `false`, the viewer has regained tracking, and that their new position represents a correction from the previously emulated values. This is typically the desired behavior if your site or app doesn't simulate motion through the space by expressly changing the position and/or orientation of the viewer (rather than the user's physical movements being used by the XR device to introduce movement).

However, if that kind of "teleportation" is being used, you actually want to avoid jumping the user's position after tracking recovery, this can introduce additional and potentially jarring jumping. Instead of allowing this to happen, you can integrate the `emulatedPosition` into the teleportation offset calculated prior to calling `getOffsetReferenceSpace()` to create a new reference space whose updated effective origin is adjusted by the distance the viewer's position jumped since the previous frame. This way, the user's position only changes once rather than twice.

### The effect of discontinuity size

The `reset` event won't be fired when the discontinuity is small enough that the device is able to regain tracking within the same tracking area. Nor will be fired at an unbounded reference space as it makes small adjustments to its native origin over time to maintain the space's stability in the vicinity of the user; only large discontinuities will trigger a reset.

Examples
--------

To add a handler for the `reset` event, you can use either of two approaches. First, you can use the `addEventListener()` method:

```js
viewerRefSpace.addEventListener("reset", (event) => {
  /\* perform reset related tasks \*/
});
```

The second option is to set the `XRReferenceSpace` object's `onreset` event handler property:

```js
viewerRefSpace.onreset = (event) => {
  /\* perform reset related tasks \*/
};
```

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

| Specification |
| --- |
| WebXR Device API # eventdef-xrreferencespace-reset |
| WebXR Device API # dom-xrreferencespace-onreset |

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

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


Using Pointer Events - Web APIs

Using Pointer Events
====================

This guide demonstrates how to use pointer events and the HTML `<canvas>` element to build a multi-touch enabled drawing application. This example is based on the one in the touch events overview, except it uses the pointer events input event model. Another difference is that because pointer events are pointer device agnostic, the application accepts coordinate-based inputs from a mouse, a pen, or a fingertip using the same code.

This application will only work on a browser that supports pointer events.

A live version of this application is available on GitHub. The source code is available on GitHub and pull requests and bug reports are welcome.

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

Surface

A touch-sensitive surface. This may be a trackpad, a touch screen, or even a virtual mapping of a user's desk surface (or mousepad) with the physical screen.

Touch point

A point of contact with the surface. This may be a finger (or elbow, ear, nose, whatever, but typically a finger), stylus, mouse, or any other method for specifying a single point on the surface.

Example
-------

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

### Create a canvas

The `touch-action` property is set to `none` to prevent the browser from applying its default touch behavior to the application.

```html
<canvas
 id="canvas"
 width="600"
 height="600"
 style="border:solid black 1px; touch-action:none">
  Your browser does not support canvas element.
</canvas>
<br />
<button onclick="startup()">Initialize</button>
<br />
Log:
<pre id="log" style="border: 1px solid #ccc;"></pre>
```

### Setting up the event handlers

When the page loads, the `startup()` function shown below should be called by our `<body>` element's `onload` attribute (but in the example we use a button to trigger it, due to limitations of the MDN live example system).

```js
function startup() {
  const el = document.getElementsByTagName("canvas")[0];
  el.addEventListener("pointerdown", handleStart, false);
  el.addEventListener("pointerup", handleEnd, false);
  el.addEventListener("pointercancel", handleCancel, false);
  el.addEventListener("pointermove", handleMove, false);
  log("initialized.");
}
```

This sets up all the event listeners for our `<canvas>` element so we can handle the touch events as they occur.

#### Tracking new touches

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

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

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

```js
function handleStart(evt) {
  log("pointerdown.");
  const el = document.getElementsByTagName("canvas")[0];
  const ctx = el.getContext("2d");

  log(`pointerdown: id = ${evt.pointerId}`);
  ongoingTouches.push(copyTouch(evt));
  const color = colorForTouch(evt);
  ctx.beginPath();
  ctx.arc(touches[i].pageX, touches[i].pageY, 4, 0, 2 \* Math.PI, false); // a circle at the start
  ctx.arc(evt.clientX, evt.clientY, 4, 0, 2 \* Math.PI, false); // a circle at the start
  ctx.fillStyle = color;
  ctx.fill();
}
```

After storing some of the event's processing in the `ongoingTouches` for later processing, the start point is drawn 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 pointers move

Each time one or more pointers moves, a `pointermove` 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) {
  const el = document.getElementsByTagName("canvas")[0];
  const ctx = el.getContext("2d");
  const color = colorForTouch(evt);
  const idx = ongoingTouchIndexById(evt.pointerId);

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

    ongoingTouches.splice(idx, 1, copyTouch(evt)); // swap in the new touch record
    log(".");
  } else {
    log(`can't figure out which touch to continue: idx = ${idx}`);
  }
}
```

This function 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 `PointerEvent.pointerId` property. This property is a unique integer for each pointer event, 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 touch point with the current information in the `ongoingTouches` array.

#### Handling the end of a touch

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

```js
function handleEnd(evt) {
  log("pointerup");
  const el = document.getElementsByTagName("canvas")[0];
  const ctx = el.getContext("2d");
  const color = colorForTouch(evt);
  const idx = ongoingTouchIndexById(evt.pointerId);

  if (idx >= 0) {
    ctx.lineWidth = 4;
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
    ctx.lineTo(evt.clientX, evt.clientY);
    ctx.fillRect(evt.clientX - 4, evt.clientY - 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 touch point.

#### Handling canceled touches

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

```js
function handleCancel(evt) {
  log(`pointercancel: id = ${evt.pointerId}`);
  const idx = ongoingTouchIndexById(evt.pointerId);
  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

In order 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.pointerId % 16;
  let g = Math.floor(touch.pointerId / 3) % 16;
  let b = Math.floor(touch.pointerId / 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}`;
  log(`color for touch with identifier ${touch.pointerId} = ${color}`);
  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 `PointerEvent.pointerId` value of 10, the resulting string is "#aaa".

#### Copying a touch object

Some browsers may re-use touch objects between events, so it's best to copy the bits you care about, rather than referencing the entire object.

```js
function copyTouch(touch) {
  return {
    identifier: touch.pointerId,
    pageX: touch.clientX,
    pageY: touch.clientY,
  };
}
```

#### 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 p = document.getElementById("log");
  p.innerHTML = `${msg}\n${p.innerHTML}`;
}
```

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

| Specification |
| --- |
| Pointer Events # pointerevent-interface |

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

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

See also
--------

* Pointer events
* Touch events


Multi-touch interaction - Web APIs

Multi-touch interaction
=======================

Pointer events extend DOM input events to support various pointing input devices such as pen/stylus and touch screens as well as mouse. 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, applications and provide a good user experience regardless of the user's hardware.

Pointer events have many similarities to mouse events but they support multiple simultaneous pointers such as multiple fingers on a touch screen. This additional feature can be used to provide richer user interaction models but at the cost of additional complexity in the multi-touch interaction handling. This document demonstrates via example code, using pointer events with different multi-touch interactions.

A *live* version of this application is available on GitHub. The source code is available on GitHub; pull requests and bug reports are welcome.

Example
-------

This example demonstrates using pointer events' various event types (`pointerdown`, `pointermove`, `pointerup` `pointercancel`, etc.) for different multi-touch interactions.

### Define touch targets

The application uses `<div>` to define three different touch target areas.

```html
<style>
 div {
 margin: 0em;
 padding: 2em;
 }
 #target1 {
 background: white;
 border: 1px solid black;
 }
 #target2 {
 background: white;
 border: 1px solid black;
 }
 #target3 {
 background: white;
 border: 1px solid black;
 }
</style>
```

### Global state

To support multi-touch interaction, preserving a pointer's event state during various event phases is required. This application uses three arrays to cache event state, one cache per target element.

```js
// Log events flag
const logEvents = false;

// Event caches, one per touch target
const evCache1 = [];
const evCache2 = [];
const evCache3 = [];
```

### Register event handlers

Event handlers are registered for the following pointer events: `pointerdown`, `pointermove` and `pointerup`. The handler for `pointerup` is used for the `pointercancel`, `pointerout` and `pointerleave` events, since these four events have the same semantics in this application.

```js
function setHandlers(name) {
  // Install event handlers for the given element
  const el = document.getElementById(name);
  el.onpointerdown = pointerdownHandler;
  el.onpointermove = pointermoveHandler;

  // Use same handler for pointer{up,cancel,out,leave} events since
  // the semantics for these events - in this app - are the same.
  el.onpointerup = pointerupHandler;
  el.onpointercancel = pointerupHandler;
  el.onpointerout = pointerupHandler;
  el.onpointerleave = pointerupHandler;
}

function init() {
  setHandlers("target1");
  setHandlers("target2");
  setHandlers("target3");
}
```

### Pointer down

The `pointerdown` event is fired when a pointer (mouse, pen/stylus or touch point on a touchscreen) makes contact with the *contact surface*. The event's state must be cached, in case this down event is part of a multi-touch interaction.

In this application, when a pointer is placed down on an element, the background color of the element changes, depending on the number of active touch points the element has. See the `update_background` function for more details about the color changes.

```js
function pointerdownHandler(ev) {
  // The pointerdown event signals the start of a touch interaction.
  // Save this event for later processing (this could be part of a
  // multi-touch interaction) and update the background color
  pushEvent(ev);
  if (logEvents) {
    log(`pointerDown: name = ${ev.target.id}`, ev);
  }
  updateBackground(ev);
}
```

### Pointer move

The `pointermove` handler is called when the pointer moves. It may be called multiple times (for example, if the user moves the pointer) before a different event type is fired.

In this application, a pointer move is represented by the target's border being set to `dashed` to provide a clear visual indication that the element has received this event.

```js
function pointermoveHandler(ev) {
  // Note: if the user makes more than one "simultaneous" touch, most browsers
  // fire at least one pointermove event and some will fire several pointermoves.
  //
  // This function sets the target element's border to "dashed" to visually
  // indicate the target received a move event.
  if (logEvents) {
    log("pointerMove", ev);
  }
  updateBackground(ev);
  ev.target.style.border = "dashed";
}
```

### Pointer up

The `pointerup` event is fired when a pointer is raised from the *contact surface*. When this occurs, the event is removed from the associated event cache.

In this application, this handler is also used for `pointercancel`, `pointerleave` and `pointerout` events.

```js
function pointerupHandler(ev) {
  if (logEvents) {
    log(ev.type, ev);
  }
  // Remove this touch point from the cache and reset the target's
  // background and border
  removeEvent(ev);
  updateBackground(ev);
  ev.target.style.border = "1px solid black";
}
```

### Application UI

The application uses `<div>` elements for the touch areas and provides buttons to enable logging and to clear the log.

To prevent the browser's default touch behavior from overriding this application's pointer handling, the `touch-action` property is applied to the `<body>` element.

```html
<body onload="init();" style="touch-action:none">
  <div id="target1">Tap, Hold or Swipe me 1</div>
  <div id="target2">Tap, Hold or Swipe me 2</div>
  <div id="target3">Tap, Hold or Swipe me 3</div>

  <!-- UI for logging/debugging -->
  <button id="log" onclick="enableLog(event);">Start/Stop event logging</button>
  <button id="clearlog" onclick="clearLog(event);">Clear the log</button>
  <p></p>
  <output></output>
</body>
```

### Miscellaneous functions

These functions support the application but aren't directly involved with the event flow.

#### Cache management

These functions manage the global event caches `evCache1`, `evCache2` and `evCache3`.

```js
function getCache(ev) {
  // Return the cache for this event's target element
  switch (ev.target.id) {
    case "target1":
      return evCache1;
    case "target2":
      return evCache2;
    case "target3":
      return evCache3;
    default:
      log("Error with cache handling", ev);
  }
}

function pushEvent(ev) {
  // Save this event in the target's cache
  const evCache = getCache(ev);
  evCache.push(ev);
}

function removeEvent(ev) {
  // Remove this event from the target's cache
  const evCache = getCache(ev);
  const index = evCache.findIndex(
    (cachedEv) => cachedEv.pointerId === ev.pointerId,
  );
  evCache.splice(index, 1);
}
```

#### Update background color

The background color of the touch areas will change as follows: no active touches is `white`; one active touch is `yellow`; two simultaneous touches is `pink` and three or more simultaneous touches is `lightblue`.

```js
function updateBackground(ev) {
  // Change background color based on the number of simultaneous touches/pointers
  // currently down:
  // white - target element has no touch points i.e. no pointers down
  // yellow - one pointer down
  // pink - two pointers down
  // lightblue - three or more pointers down
  const evCache = getCache(ev);
  switch (evCache.length) {
    case 0:
      // Target element has no touch points
      ev.target.style.background = "white";
      break;
    case 1:
      // Single touch point
      ev.target.style.background = "yellow";
      break;
    case 2:
      // Two simultaneous touch points
      ev.target.style.background = "pink";
      break;
    default:
      // Three or more simultaneous touches
      ev.target.style.background = "lightblue";
  }
}
```

#### Event logging

These functions are used send to event activity to the application window (to support debugging and learning about the event flow).

```js
// Log events flag
let logEvents = false;

function enableLog(ev) {
  logEvents = !logEvents;
}

function log(name, ev) {
  const o = document.getElementsByTagName("output")[0];
  const s =
    `${name}:<br>` +
    ` pointerID = ${ev.pointerId}<br>` +
    ` pointerType = ${ev.pointerType}<br>` +
    ` isPrimary = ${ev.isPrimary}`;
  o.innerHTML += `${s}<br>`;
}

function clearLog(event) {
  const o = document.getElementsByTagName("output")[0];
  o.innerHTML = "";
}
```


Pinch zoom gestures - Web APIs

Pinch zoom gestures
===================

Adding *gestures* to an application can significantly improve the user experience. There are many types of gestures, from the simple single-touch *swipe* gesture to the more complex multi-touch *twist* gesture, where the touch points (aka *pointers*) move in different directions.

This example shows how to detect the *pinch/zoom* gesture, which uses `pointer events` to detect whether the user moves two pointers closer or farther apart from each other.

A *live* version of this application is available on GitHub. The source code is available on GitHub; pull requests and bug reports are welcome.

Example
-------

In this example, you use the `pointer events` to simultaneously detect two pointing devices of any type, including fingers, mice, and pens. The pinch in (zoom out) gesture, which moves the two pointers toward each other, changes the target element's background color to `lightblue`. The pinch out (zoom in) gesture, which moves the two pointers away from each other, changes the target element's background color to `pink`.

### Define touch target

The application uses `<div>` to define the pointers' target areas.

```html
<style>
 div {
 margin: 0em;
 padding: 2em;
 }
 #target {
 background: white;
 border: 1px solid black;
 }
</style>
```

### Global state

Supporting a two-pointer gesture requires preserving a pointer's event state during various event phases. This application uses two global variables to cache the event state.

```js
// Global vars to cache event state
const evCache = [];
let prevDiff = -1;
```

### Register event handlers

Event handlers are registered for the following pointer events: `pointerdown`, `pointermove` and `pointerup`. The handler for `pointerup` is used for the `pointercancel`, `pointerout` and `pointerleave` events since these four events have the same semantics in this application.

```js
function init() {
  // Install event handlers for the pointer target
  const el = document.getElementById("target");
  el.onpointerdown = pointerdownHandler;
  el.onpointermove = pointermoveHandler;

  // Use same handler for pointer{up,cancel,out,leave} events since
  // the semantics for these events - in this app - are the same.
  el.onpointerup = pointerupHandler;
  el.onpointercancel = pointerupHandler;
  el.onpointerout = pointerupHandler;
  el.onpointerleave = pointerupHandler;
}
```

### Pointer down

The `pointerdown` event is fired when a pointer (mouse, pen/stylus or touch point on a touchscreen) makes contact with the *contact surface*. In this application, the event's state must be cached in case this down event is part of a two-pointer pinch/zoom gesture.

```js
function pointerdownHandler(ev) {
  // The pointerdown event signals the start of a touch interaction.
  // This event is cached to support 2-finger gestures
  evCache.push(ev);
  log("pointerDown", ev);
}
```

### Pointer move

The `pointermove` event handler detects if a user is invoking a two-pointer pinch/zoom gesture. If two pointers are down, and the distance between the pointers is increasing (signifying a pinch out or zoom in), the element's background color is changed to `pink`, and if the distance between the pointers is decreasing (a pinch in or zoom out), the background color is changed to `lightblue`. In a more sophisticated application, pinch in or pinch out determination could be used to apply application-specific semantics.

When this event is processed, the target's border is set to `dashed` to provide a clear visual indication the element has received a move event.

```js
function pointermoveHandler(ev) {
  // This function implements a 2-pointer horizontal pinch/zoom gesture.
  //
  // If the distance between the two pointers has increased (zoom in),
  // the target element's background is changed to "pink" and if the
  // distance is decreasing (zoom out), the color is changed to "lightblue".
  //
  // This function sets the target element's border to "dashed" to visually
  // indicate the pointer's target received a move event.
  log("pointerMove", ev);
  ev.target.style.border = "dashed";

  // Find this event in the cache and update its record with this event
  const index = evCache.findIndex(
    (cachedEv) => cachedEv.pointerId === ev.pointerId,
  );
  evCache[index] = ev;

  // If two pointers are down, check for pinch gestures
  if (evCache.length === 2) {
    // Calculate the distance between the two pointers
    const curDiff = Math.abs(evCache[0].clientX - evCache[1].clientX);

    if (prevDiff > 0) {
      if (curDiff > prevDiff) {
        // The distance between the two pointers has increased
        log("Pinch moving OUT -> Zoom in", ev);
        ev.target.style.background = "pink";
      }
      if (curDiff < prevDiff) {
        // The distance between the two pointers has decreased
        log("Pinch moving IN -> Zoom out", ev);
        ev.target.style.background = "lightblue";
      }
    }

    // Cache the distance for the next move event
    prevDiff = curDiff;
  }
}
```

### Pointer up

The `pointerup` event is fired when a pointer is raised from the *contact surface*. When this occurs, the event is removed from the event cache and the target element's background color and border are restored to their original values.

In this application, this handler is also used for `pointercancel`, `pointerleave` and `pointerout` events.

```js
function pointerupHandler(ev) {
  log(ev.type, ev);
  // Remove this pointer from the cache and reset the target's
  // background and border
  removeEvent(ev);
  ev.target.style.background = "white";
  ev.target.style.border = "1px solid black";

  // If the number of pointers down is less than two then reset diff tracker
  if (evCache.length < 2) {
    prevDiff = -1;
  }
}
```

### Application UI

The application uses a `<div>` element for the touch area and provides buttons to enable logging and to clear the log.

To prevent the browser's default touch behavior from overriding this application's pointer handling, the `touch-action` property is applied to the `<body>` element.

```html
<body onload="init();" style="touch-action:none">
  <div id="target">
    Touch and Hold with 2 pointers, then pinch in or out.<br />
    The background color will change to pink if the pinch is opening (Zoom In)
    or changes to lightblue if the pinch is closing (Zoom out).
  </div>
  <!-- UI for logging/debugging -->
  <button id="log" onclick="enableLog(event);">Start/Stop event logging</button>
  <button id="clearlog" onclick="clearLog(event);">Clear the log</button>
  <p></p>
  <output></output>
</body>
```

### Miscellaneous functions

These functions support the application but aren't directly involved in the event flow.

#### Cache management

This function helps manage the global event caches `evCache`.

```js
function removeEvent(ev) {
  // Remove this event from the target's cache
  const index = evCache.findIndex(
    (cachedEv) => cachedEv.pointerId === ev.pointerId,
  );
  evCache.splice(index, 1);
}
```

#### Event logging

These functions are used to send event activity to the application's window (to support debugging and learning about the event flow).

```js
// Log events flag
let logEvents = false;

// Logging/debugging functions
function enableLog(ev) {
  logEvents = !logEvents;
}

function log(prefix, ev) {
  if (!logEvents) return;
  const o = document.getElementsByTagName("output")[0];
  const s =
    `${prefix}:<br>` +
    ` pointerID = ${ev.pointerId}<br>` +
    ` pointerType = ${ev.pointerType}<br>` +
    ` isPrimary = ${ev.isPrimary}`;
  o.innerHTML += `${s}<br>`;
}

function clearLog(event) {
  const o = document.getElementsByTagName("output")[0];
  o.innerHTML = "";
}
```

See also
--------

* Pointer Events now in Firefox Nightly; Mozilla Hacks; by Matt Brubeck and Jason Weathersby; 2015-Aug-04
* jQuery Pointer Events Polyfill
* Gestures; Material Design


Web Push API Notifications best practices - Web APIs

Web Push API Notifications best practices
=========================================

This article provides a useful summary of best practices to keep in mind when developing websites and applications that use Push Notifications for user engagement.

>
> "If done well, it's nice to have, but if not done well, it's really annoying." — Overheard conversation between two browser developers discussing the ethics of push notifications.
>
>
>

Overview of web push notifications
----------------------------------

Web Push Notifications (created using a combination of the Notifications, Push, and Service Worker APIs) are part of the rising noise that product developers and marketers are using to get attention for their sites. Searching the web for "web push notifications," you'll find articles from marketing experts who believe you should use push to re-engage people who have left your site so they can complete a purchase, or be sent the latest news, or receive links to recommended products.

### The dark side

Their novelty provides a new and unexploited opportunity for enterprising sites to reach potential customers. Has the customer switched tabs to answer an email? Win them back with an expiring offer of free shipping that they can't ignore!

But really, is this the best use of push notifications? Or is it a new iteration on the old and tired pop-up ad?

>
> "Web push doesn't risk ending up in the spam folder. Nor can it be blocked by ad blockers. It shows right up on your desktop even when the website is shut. In mobile, it shows up in the notification tray, just like app push notifications, even when the browser is not running." — an unnamed marketing site
>
>
>

### Positive uses of push

But there's a bright and useful side to push notifications, too. Let's say you and your team commonly use a chat program to communicate, but today you're happily working somewhere, and problem comes up. Say your program manager found a hiccup in the approvals and wants to get your feedback on something before she proceeds.

After a few failed attempts to get your attention, they send you an email, and your email app produces a push notification that successfully alerts you, even though your mail web app is not open.

In this document, we'll talk about the ethical use of web push notifications. Sometimes they can eliminate frustration and annoyance, and sometimes they can cause them, and it's up to you as a developer to make wise recommendations (and decisions) about the use of push notifications.

What are you hoping to achieve with this push notification?
-----------------------------------------------------------

As with everything, with great power comes great responsibility. Every push notification should be useful and time-sensitive, and the user should always be asked for permission before sending the first one, and be offered an easy way to opt out of getting more in the future.

There are some basic questions you can answer to determine if a push notification is needed:

* Is there someone waiting in real-time for a response? In our above example, the program manager is awaiting your response and so a push notification is appropriate.
* Is up-to-the minute updating necessary? I use a service that aggregates different social media news sources. When a story I'm interested in is trending, I'd like to get a notification!
* Is there breaking news that is timely? This is where it gets a little tricky. Sometimes news sites request push notifications so they can essentially say "Look at me! Look at me!" It all comes down to what the user wants, and you can use behavior to determine intent. For example, if the user views more than one article, or lingers on your page for several minutes, they may be interested in receiving updates.

In addition to the question of whether a push notification is required at all, there are many different types of push notifications, ranging from casual-and-disappearing to persistent-and-requiring-interaction.

We caution you to use the interaction-requiring ones very sparingly, since they can be the most annoying. Your notifications should be assistive, not disruptive.

Building trust
--------------

Some studies have shown that as many as 60% of push notifications are blocked. Allowing your site to push notifications in realtime requires trust. You can build trust by having a well-designed website that provides good content that shows respect for the user, and a clear value to accepting push notifications.

Browser mitigations
-------------------

Because of abuses of push notifications in the past, web browser developers have begun to implement strategies to help mitigate this problem. For example, Safari 12.1 now requires—and other browsers either already do, or are planning to do so—that the user interact with the page in some way before the page can request permission to perform push notifications. This at least prevents the user from getting spontaneously asked this question on web pages that they've only glanced at once may rarely if ever look at again.

In the case of Firefox, see Firefox bug 1524619, in which we find that Firefox 68 implements this, disabled by default, behind the preference `dom.webnotifications.requireuserinteraction`.

See also
--------

* Notifications API
* Using the Notifications API
* Push API


SpeechRecognitionErrorEvent: message property - Web APIs

SpeechRecognitionErrorEvent: message property
=============================================

 The **`message`** read-only property of the
 `SpeechRecognitionErrorEvent` interface returns a message describing the
 error in more detail.

Value
-----

 A string containing more details about the error that was raised.
 Note that the spec does not define the exact wording of these messages — this is up to
 the implementors to decide upon.

Examples
--------

```js
const recognition = new SpeechRecognition();

recognition.onerror = (event) => {
  console.log(`Speech recognition error detected: ${event.error}`);
  console.log(`Additional information: ${event.message}`);
};
```

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

| Specification |
| --- |
| Web Speech API # dom-speechrecognitionerrorevent-message |

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

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

See also
--------

* Web Speech API


SpeechRecognitionErrorEvent: error property - Web APIs

SpeechRecognitionErrorEvent: error property
===========================================

 The **`error`** read-only property of the
 `SpeechRecognitionErrorEvent` interface returns the type of error raised.

Value
-----

A string naming the type of error. The possible error types are:

`no-speech`

No speech was detected.

`aborted`

 Speech input was aborted in some manner, perhaps by some user-agent-specific
 behavior like a button the user can press to cancel speech input.

`audio-capture`

Audio capture failed.

`network`

Network communication required for completing the recognition failed.

`not-allowed`

 The user agent disallowed any speech input from occurring for reasons of security,
 privacy or user preference.

`service-not-allowed`

 The user agent disallowed the requested speech recognition service, either because
 the user agent doesn't support it or because of reasons of security, privacy or user
 preference. In this case it would allow another more suitable speech recognition
 service to be used instead.

`bad-grammar`

 There was an error in the speech recognition grammar or semantic tags, or the chosen
 grammar format or semantic tag format was unsupported.

`language-not-supported`

The user agent does not support the language specified in the value of `lang` attribute of the `SpeechRecognition` object. The set of supported languages is browser-dependent, and from frontend code there is no way to programmatically determine what languages a user's browser supports for speech recognition.

Examples
--------

```js
const recognition = new SpeechRecognition();

recognition.onerror = (event) => {
  console.log(`Speech recognition error detected: ${event.error}`);
  console.log(`Additional information: ${event.message}`);
};
```

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

| Specification |
| --- |
| Web Speech API # dom-speechrecognitionerrorevent-error |

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

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

See also
--------

* Web Speech API


FileReaderSync: readAsDataURL() method - Web APIs

FileReaderSync: readAsDataURL() method
======================================

The **`readAsDataURL()`** method of the `FileReaderSync` interface allows to read `File` or `Blob` objects in a synchronous way into a string representing a data URL. This interface is only available in workers as it enables synchronous I/O that could potentially block.

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

Syntax
------

```js
readAsDataURL(File)
readAsDataURL(Blob)
```

### Parameters

`blob`

The `File` or `Blob` to read.

### Return value

A string representing the input data as a data URL.

Exceptions
----------

The following exceptions can be raised by this method:

`NotFoundError` `DOMException`

Thrown if the resource represented by the DOM `File` or `Blob` cannot be found, e.g. because it has been erased.

`SecurityError` `DOMException`

Thrown if one of the following problematic situation is detected:

* the resource has been modified by a third party;
* too many read are performed simultaneously;
* the file pointed by the resource is unsafe for a use from the Web (like it is a system file).

`NotReadableError` `DOMException`

Thrown if the resource cannot be read due to a permission problem, like a concurrent lock.

`EncodingError` `DOMException`

Thrown if the resource is a data URL and exceed the limit length defined by each browser.

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

| Specification |
| --- |
| File API # readAsDataURLSync-section |

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

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

See also
--------

* File and Directory Entries API
* `File`
* `FileReaderSync`
* `FileReader`
* `Blob`


FileReaderSync: readAsText() method - Web APIs

FileReaderSync: readAsText() method
===================================

The **`readAsText()`** method of the `FileReaderSync` interface allows to read `File` or `Blob` objects in a synchronous way into a string. This interface is only available in workers as it enables synchronous I/O that could potentially block.

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

Syntax
------

```js
readAsText(File)
readAsText(Blob)
readAsText(File, encoding)
readAsText(Blob, encoding)
```

### Parameters

`blob`

The `File` or `Blob` to read.

`encoding`

The optional parameter specifies encoding to be used (e.g., `iso-8859-1` or `UTF-8`). If not present, the method will apply a detection algorithm for it.

### Return value

A string representing the input data.

Exceptions
----------

The following exceptions can be raised by this method:

`NotFoundError` `DOMException`

Thrown if the resource represented by the DOM `File` or `Blob` cannot be found, e.g. because it has been erased.

`SecurityError` `DOMException`

Thrown if one of the following problematic situation is detected:

* the resource has been modified by a third party;
* too many read are performed simultaneously;
* the file pointed by the resource is unsafe for a use from the Web (like it is a system file).

`NotReadableError` `DOMException`

Thrown if the resource cannot be read due to a permission problem, like a concurrent lock.

`EncodingError` `DOMException`

Thrown if the resource is a data URL and exceed the limit length defined by each browser.

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

| Specification |
| --- |
| File API # readAsTextSync |

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

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

See also
--------

* File API
* `File`
* `FileReaderSync`
* `FileReader`
* `Blob`


FileReaderSync: readAsBinaryString() method - Web APIs

FileReaderSync: readAsBinaryString() method
===========================================

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

**Note:** This method is deprecated in favor of `readAsArrayBuffer()`.

The **`readAsBinaryString()`** method of the `FileReaderSync` interface allows to read `File` or `Blob` objects in a synchronous way into a string. This interface is only available in workers as it enables synchronous I/O that could potentially block.

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

Syntax
------

```js
readAsBinaryString(File)
readAsBinaryString(Blob)
```

### Parameters

`blob`

The `File` or `Blob` to read.

### Return value

A string representing the input data.

Exceptions
----------

`NotFoundError` `DOMException`

Thrown if the resource represented by the DOM `File` or `Blob` cannot be found, e.g. because it has been erased.

`SecurityError` `DOMException`

Thrown if one of the following problematic situation is detected:

* the resource has been modified by a third party;
* too many read are performed simultaneously;
* the file pointed by the resource is unsafe for a use from the Web (like it is a system file).

`NotReadableError` `DOMException`

Thrown if the resource cannot be read due to a permission problem, like a concurrent lock.

`EncodingError` `DOMException`

Thrown if the resource is a data URL and exceed the limit length defined by each browser.

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

| Specification |
| --- |
| File API # readAsBinaryStringSyncSection |

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

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

See also
--------

* File API
* `File`
* `FileReaderSync`
* `FileReader`
* `Blob`


FileReaderSync: readAsArrayBuffer() method - Web APIs

FileReaderSync: readAsArrayBuffer() method
==========================================

The **`readAsArrayBuffer()`** method of the `FileReaderSync` interface allows to read `File` or `Blob` objects in a synchronous way into an `ArrayBuffer`. This interface is only available in workers as it enables synchronous I/O that could potentially block.

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

Syntax
------

```js
readAsArrayBuffer(blob)
```

### Parameters

`blob`

The `File` or `Blob` to read into the `File` or `ArrayBuffer`.

### Return value

An `ArrayBuffer` representing the file's data.

Exceptions
----------

The following exceptions can be raised by this method:

`NotFoundError` `DOMException`

Thrown if the resource represented by the DOM `File` or `Blob` cannot be found, e.g. because it has been erased.

`SecurityError` `DOMException`

Thrown if one of the following problematic situation is detected:

* the resource has been modified by a third party;
* too many read are performed simultaneously;
* the file pointed by the resource is unsafe for a use from the Web (like it is a system file).

`NotReadableError` `DOMException`

Thrown if the resource cannot be read due to a permission problem, like a concurrent lock.

`EncodingError` `DOMException`

Thrown if the resource is a data URL and exceed the limit length defined by each browser.

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

| Specification |
| --- |
| File API # readAsArrayBufferSyncSection |

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

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

See also
--------

* File API
* `File`
* `FileReaderSync`
* `FileReader`
* `Blob`


FileReaderSync: FileReaderSync() constructor - Web APIs

FileReaderSync: FileReaderSync() constructor
============================================

The **`FileReaderSync()`** constructor creates a new `FileReaderSync`.

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

Syntax
------

```js
new FileReaderSync()
```

### Parameters

None.

Examples
--------

The following code snippet shows creation of a `FileReaderSync` object using the `FileReaderSync()` constructor and subsequent usage of the object:

```js
function readFile(blob) {
  const reader = new FileReaderSync();
  postMessage(reader.readAsDataURL(blob));
}
```

**Note:** This snippet must be used inside a `Worker`, as synchronous interfaces can't be used on the main thread.

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

| Specification |
| --- |
| File API # filereadersyncConstrctr |

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

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


PresentationRequest: getAvailability() method - Web APIs

PresentationRequest: getAvailability() method
=============================================

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

When the `getAvailability()` method is called, the user agent *MUST* run the following steps:

Input

*presentationUrls*, a list of presentation request URLs

Output

*P*, a Promise

1. If one of the following conditions is true:
    * The result of running the prohibits mixed security contexts algorithm on the document's settings object is `"Prohibits Mixed Security Contexts"` and *presentationUrl* is an a priori unauthenticated URL.
    * The document object's active sandboxing flag set has the sandboxed presentation browsing context flag set.Run the following substeps:
    1. Return a Promise rejected with a `SecurityError` `DOMException`.
    2. Abort these steps.
2. Let *P* be a new Promise.
3. Return *P*, but continue running these steps in parallel.
4. If the user agent is unable to monitor the list of available presentation displays for the entire duration of the controlling browsing context (e.g., because the user has disabled this feature), then:
    1. Resolve *P* with a new `PresentationAvailability` object with its `value` property set to `false`.
    2. Abort all the remaining steps.
5. If the user agent is unable to continuously monitor the list of available presentation displays but can find presentation displays in order to start a connection, then:
    1. Reject *P* with a `NotSupportedError` `DOMException`.
    2. Abort all the remaining steps.
6. If there exists a tuple (*A*, *presentationUrls*) in the set of availability objects, then:
    1. Resolve *P* with *A*.
    2. Abort all the remaining steps.
7. Let *A* be a new `PresentationAvailability` object with its `value` property set as follows:
    1. `false` if the list of available presentation displays is empty.
    2. `true` if there is at least one compatible presentation display for some member of *presentationUrls*. Meaning there is an entry *(presentationUrl, display)* in the list of available presentation displays for some *presentationUrl* in *presentationUrls*.
    3. `false` otherwise.
8. Create a tuple (*A*, *presentationUrls*) and add it to the set of availability objects.
9. Run the algorithm to monitor the list of available presentation displays.
10. Resolve *P* with *A*.
Browser compatibility
---------------------

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


PresentationRequest: start() method - Web APIs

PresentationRequest: start() method
===================================

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

The **`start()`** property of the `PresentationRequest` interface returns a `Promise` that resolves with a `PresentationConnection` after the user agent prompts the user to select a display and grant permission to use that display.

Syntax
------

```js
start()
```

### Parameters

None.

### Return value

A `Promise` that resolves with a `PresentationConnection`.

Security
--------

Transient user activation is required. The user has to interact with the page or a UI element in order for this feature to work.

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

| Specification |
| --- |
| Presentation API # selecting-a-presentation-display |

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

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


PresentationRequest: reconnect() method - Web APIs

PresentationRequest: reconnect() method
=======================================

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

When the `reconnect(presentationId)` method is called on a `PresentationRequest` *presentationRequest*, the user agent *MUST* run the following steps to *reconnect to a presentation*:

Input
-----

* *presentationRequest*, the `PresentationRequest` object that `reconnect()` was called on.
* *presentationId*, a valid presentation identifier
Output
------

*P*, a Promise.

Algorithm
---------

1. Using the document's settings object run the prohibits mixed security contexts algorithm.
2. If the result of the algorithm is `"Prohibits Mixed Security Contexts"` and the presentation request URL of *presentationRequest* is an a priori unauthenticated URL, then return a Promise rejected with a `SecurityError` and abort these steps.
3. If the document object's active sandboxing flag set has the sandboxed presentation browsing context flag set, then return a Promise rejected with a `SecurityError` and abort these steps.
4. Let *P* be a new Promise.
5. Return *P* but continue running these steps in parallel.
6. Search the set of controlled presentations for a `PresentationConnection` that meets the following criteria: its controlling browsing context is the current browsing context, its presentation connection state is not `terminated`, its presentation URL is equal to one of the presentation request URLs of *presentationRequest* and its presentation identifier is equal to *presentationId*.
7. If such a `PresentationConnection` exists, run the following steps:
    1. Let *S* be that `PresentationConnection`.
    2. Resolve *P* with *S*.
    3. If the presentation connection state of *S* is `connecting` or `connected`, then abort all remaining steps.
    4. Set the presentation connection state of *S* to `connecting`.
    5. Establish a presentation connection with *S*.
    6. Abort all remaining steps.
8. Search the set of controlled presentations for the first `PresentationConnection` that meets the following criteria: its presentation connection state is not `terminated`, its presentation URL is equal to one of the presentation request URLs of *presentationRequest*, and its presentation identifier is equal to *presentationId*.
9. If such a `PresentationConnection` exists, let *E* be that `PresentationConnection`, and run the following steps:
    1. Create a new `PresentationConnection` *S*.
    2. Set the presentation identifier of *S* to *presentationId*.
    3. Set the presentation URL of *S* to the presentation URL of *E*.
    4. Set the presentation connection state of *S* to `connecting`.
    5. Add *S* to the set of controlled presentations.
    6. Resolve *P* with *S*.
    7. Queue a task to fire a trusted event with the name `connectionavailable`, that uses the `PresentationConnectionAvailableEvent` interface with the `connection` attribute initialized to *S*, at *presentationRequest*. The event must not bubble and cancelable and should have no default action.
    8. Establish a presentation connection with *S*.
    9. Abort all remaining steps.
10. Reject *P* with a `NotFoundError` exception.
Browser compatibility
---------------------

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


PresentationRequest: PresentationRequest() constructor - Web APIs

PresentationRequest: PresentationRequest() constructor
======================================================

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

 The **`PresentationRequest()`**
 constructor creates a new `PresentationRequest` object which creates a
 new PresentationRequest.

Syntax
------

```js
new PresentationRequest(url)
new PresentationRequest(urls)
```

### Parameters

`url` or `urls\[]`

 A URL or array of URLs that are possible URLs used to create, or reconnect, a
 presentation for the PresentationRequest instance.

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

| Specification |
| --- |
| Presentation API # constructing-a-presentationrequest |

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

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


XPathResult: booleanValue property - Web APIs

XPathResult: booleanValue property
==================================

 The read-only **`booleanValue`** property of the
 `XPathResult` interface returns the boolean value of a result with
 `XPathResult.resultType` being `BOOLEAN_TYPE`.

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

Value
-----

 The return value is the boolean value of the `XPathResult` returned by
 `Document.evaluate()`.

### Exceptions

#### TYPE\_ERR

 In case `XPathResult.resultType` is not `BOOLEAN_TYPE`, an
 `XPathException` of type `TYPE_ERR` is thrown.

Examples
--------

The following example shows the use of the `booleanValue` property.

### HTML

```html
<div>XPath example</div>
<p>Text is 'XPath example': <output></output></p>
```

### JavaScript

```js
const xpath = "//div/text() = 'XPath example'";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.BOOLEAN\_TYPE,
  null,
);
document.querySelector("output").textContent = result.booleanValue;
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-booleanvalue |

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

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


XPathResult: singleNodeValue property - Web APIs

XPathResult: singleNodeValue property
=====================================

 The read-only **`singleNodeValue`** property of the
 `XPathResult` interface returns a `Node` value or
 `null` in case no node was matched of a result with
 `XPathResult.resultType` being `ANY_UNORDERED_NODE_TYPE` or
 `FIRST_ORDERED_NODE_TYPE`.

Value
-----

 The return value is the `Node` value of the `XPathResult`
 returned by `Document.evaluate()`.

### Exceptions

#### TYPE\_ERR

 In case `XPathResult.resultType` is not
 `ANY_UNORDERED_NODE_TYPE` or `FIRST_ORDERED_NODE_TYPE`, an
 `XPathException` of type `TYPE_ERR` is thrown.

Examples
--------

The following example shows the use of the `singleNodeValue` property.

### HTML

```html
<div>XPath example</div>
<div>
  Tag name of the element having the text content 'XPath example':
  <output></output>
</div>
```

### JavaScript

```js
const xpath = "//\*[text()='XPath example']";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.FIRST\_ORDERED\_NODE\_TYPE,
  null,
);
document.querySelector("output").textContent = result.singleNodeValue.localName;
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-singlenodevalue |

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

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


XPathResult: snapshotItem() method - Web APIs

XPathResult: snapshotItem() method
==================================

 The **`snapshotItem()`** method of the
 `XPathResult` interface returns an item of the snapshot collection or
 `null` in case the index is not within the range of nodes. Unlike the
 iterator result, the snapshot does not become invalid, but may not correspond to the
 current document if it is mutated.

Syntax
------

```js
snapshotItem(i)
```

### Parameters

`i`

A number, the index of the item.

### Return value

 The `Node` at the given index within the node set of the
 `XPathResult`.

### Exceptions

#### TYPE\_ERR

 In case `XPathResult.resultType` is not
 `UNORDERED_NODE_SNAPSHOT_TYPE` or `ORDERED_NODE_SNAPSHOT_TYPE`, an
 `XPathException` of type `TYPE_ERR` is thrown.

Examples
--------

The following example shows the use of the `snapshotItem()` method.

### HTML

```html
<div>XPath example</div>
<div>Tag names of the matched nodes: <output></output></div>
```

### JavaScript

```js
const xpath = "//div";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.ORDERED\_NODE\_SNAPSHOT\_TYPE,
  null,
);
let node = null;
const tagNames = [];
for (let i = 0; i < result.snapshotLength; i++) {
  node = result.snapshotItem(i);
  tagNames.push(node.localName);
}
document.querySelector("output").textContent = tagNames.join(", ");
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-snapshotitem-index-index |

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

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


XPathResult: invalidIteratorState property - Web APIs

XPathResult: invalidIteratorState property
==========================================

 The read-only **`invalidIteratorState`** property of the
 `XPathResult` interface signifies that the iterator has become invalid. It
 is `true` if `XPathResult.resultType` is
 `UNORDERED_NODE_ITERATOR_TYPE` or `ORDERED_NODE_ITERATOR_TYPE` and
 the document has been modified since this result was returned.

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

Value
-----

A boolean value indicating whether the iterator has become invalid.

Examples
--------

The following example shows the use of the `invalidIteratorState` property.

### HTML

```html
<div>XPath example</div>
<p>Iterator state: <output></output></p>
```

### JavaScript

```js
const xpath = "//div";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.ANY\_TYPE,
  null,
);
// Invalidates the iterator state
document.querySelector("div").remove();
document.querySelector("output").textContent = result.invalidIteratorState
  ? "invalid"
  : "valid";
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-invaliditeratorstate |

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

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


XPathResult: resultType property - Web APIs

XPathResult: resultType property
================================

 The read-only **`resultType`** property of the
 `XPathResult` interface represents the type of the result, as defined by
 the type constants.

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

Value
-----

An integer value representing the type of the result, as defined by the type constants.

Constants
---------

| Result Type Defined Constant | Value | Description |
| --- | --- | --- |
| `ANY_TYPE` | `0` |
 A result set containing whatever type naturally results from evaluation
 of the expression. Note that if the result is a node-set then
 `UNORDERED_NODE_ITERATOR_TYPE` is always the resulting type.
  |
| `NUMBER_TYPE` | `1` |
 A result containing a single number. This is useful for example, in an
 XPath expression using the `count()` function.
  |
| `STRING_TYPE` | `2` | A result containing a single string. |
| `BOOLEAN_TYPE` | `3` |
 A result containing a single boolean value. This is useful for example,
 in an XPath expression using the `not()` function.
  |
| `UNORDERED_NODE_ITERATOR_TYPE` | `4` |
 A result node-set containing all the nodes matching the expression. The
 nodes may not necessarily be in the same order that they appear in the
 document.
  |
| `ORDERED_NODE_ITERATOR_TYPE` | `5` |
 A result node-set containing all the nodes matching the expression. The
 nodes in the result set are in the same order that they appear in the
 document.
  |
| `UNORDERED_NODE_SNAPSHOT_TYPE` | `6` |
 A result node-set containing snapshots of all the nodes matching the
 expression. The nodes may not necessarily be in the same order that they
 appear in the document.
  |
| `ORDERED_NODE_SNAPSHOT_TYPE` | `7` |
 A result node-set containing snapshots of all the nodes matching the
 expression. The nodes in the result set are in the same order that they
 appear in the document.
  |
| `ANY_UNORDERED_NODE_TYPE` | `8` |
 A result node-set containing any single node that matches the
 expression. The node is not necessarily the first node in the document
 that matches the expression.
  |
| `FIRST_ORDERED_NODE_TYPE` | `9` |
 A result node-set containing the first node in the document that matches
 the expression.
  |

Examples
--------

The following example shows the use of the `resultType` property.

### HTML

```html
<div>XPath example</div>
<div>Is XPath result a node set: <output></output></div>
```

### JavaScript

```js
const xpath = "//div";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.ANY\_TYPE,
  null,
);
document.querySelector("output").textContent =
  result.resultType >= XPathResult.UNORDERED\_NODE\_ITERATOR\_TYPE &&
  result.resultType <= XPathResult.FIRST\_ORDERED\_NODE\_TYPE;
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-resulttype |

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

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


XPathResult: stringValue property - Web APIs

XPathResult: stringValue property
=================================

 The read-only **`stringValue`** property of the
 `XPathResult` interface returns the string value of a result with
 `XPathResult.resultType` being `STRING_TYPE`.

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

Value
-----

 The return value is the string value of the `XPathResult` returned by
 `Document.evaluate()`.

### Exceptions

#### TYPE\_ERR

 In case `XPathResult.resultType` is not `STRING_TYPE`, an
 `XPathException` of type `TYPE_ERR` is thrown.

Examples
--------

The following example shows the use of the `stringValue` property.

### HTML

```html
<div>XPath example</div>
<div>Text content of the <div> above: <output></output></div>
```

### JavaScript

```js
const xpath = "//div/text()";
const result = document.evaluate(
  xpath,
  document,
  null,
  XPathResult.STRING\_TYPE,
  null,
);
document.querySelector("output").textContent = result.stringValue;
```

### Result

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

| Specification |
| --- |
| DOM Standard # dom-xpathresult-stringvalue |

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

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