Using Service Workers - Web APIs

Using Service Workers
=====================

This article provides information on getting started with service workers, including basic architecture, registering a service worker, the installation and activation process for a new service worker, updating your service worker, cache control and custom responses, all in the context of a simple app with offline functionality.

The premise of service workers
------------------------------

One overriding problem that web users have suffered with for years is loss of connectivity. The best web app in the world will provide a terrible user experience if you can't download it. There have been various attempts to create technologies to solve this problem, and some of the issues have been solved. But the overriding problem is that there wasn't a good overall control mechanism for asset caching and custom network requests.

Service workers fix these issues. Using a service worker you can set an app up to use cached assets first, thus providing a default experience even when offline, before then getting more data from the network (commonly known as "offline first"). This is already available with native apps, which is one of the main reasons native apps are often chosen over web apps.

A service worker functions like a proxy server, allowing you to modify requests and responses replacing them with items from its own cache.

Setting up to play with service workers
---------------------------------------

Service workers are enabled by default in all modern browsers. To run code using service workers, you'll need to serve your code via HTTPS — Service workers are restricted to running across HTTPS for security reasons. A server supporting HTTPS is necessary. To host experiments, you can use a service such as GitHub, Netlify, Vercel, etc. In order to facilitate local development, `localhost` is considered a secure origin by browsers as well.

Basic architecture
------------------

With service workers, the following steps are generally observed for basic setup:

1. The service worker code is fetched and then registered using `serviceWorkerContainer.register()`. If successful, the service worker is executed in a `ServiceWorkerGlobalScope`; this is basically a special kind of worker context, running off the main script execution thread, with no DOM access. The service worker is now ready to process events.
2. Installation takes place. An `install` event is always the first one sent to a service worker (this can be used to start the process of populating an IndexedDB, and caching site assets). During this step, the application is preparing to make everything available for use offline.
3. When the `install` handler completes, the service worker is considered installed. At this point a previous version of the service worker may be active and controlling open pages. Because we don't want two different versions of the same service worker running at the same time, the new version is not yet active.
4. Once all pages controlled by the old version of the service worker have closed, it's safe to retire the old version, and the newly installed service worker receives an `activate` event. The primary use of `activate` is to clean up resources used in previous versions of the service worker. The new service worker can call `skipWaiting()` to ask to be activated immediately without waiting for open pages to be closed. The new service worker will then receive `activate` immediately, and will take over any open pages.
5. After activation, the service worker will now control pages, but only those that were opened after the `register()` is successful. In other words, documents will have to be reloaded to actually be controlled, because a document starts life with or without a service worker and maintains that for its lifetime. To override this default behavior and adopt open pages, a service worker can call `clients.claim()`.
6. Whenever a new version of a service worker is fetched, this cycle happens again and the remains of the previous version are cleaned during the new version's activation.

![lifecycle diagram](/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers/sw-lifecycle.svg)

Here is a summary of the available service worker events:

* `install`
* `activate`
* `message`
* Functional events
    + `fetch`
    + `sync`
    + `push`
Demo
----

To demonstrate just the very basics of registering and installing a service worker, we have created a demo called simple service worker, which is a simple Star Wars Lego image gallery. It uses a promise-powered function to read image data from a JSON object and load the images using `fetch()`, before displaying the images in a line down the page. We've kept things static for now. It also registers, installs, and activates a service worker.

![The words Star Wars followed by an image of a Lego version of the Darth Vader character](/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers/demo-screenshot.png)

You can see the source code on GitHub, and the simple service worker running live.

### Registering your worker

The first block of code in our app's JavaScript file — `app.js` — is as follows. This is our entry point into using service workers.

```js
const registerServiceWorker = async () => {
  if ("serviceWorker" in navigator) {
    try {
      const registration = await navigator.serviceWorker.register("/sw.js", {
        scope: "/",
      });
      if (registration.installing) {
        console.log("Service worker installing");
      } else if (registration.waiting) {
        console.log("Service worker installed");
      } else if (registration.active) {
        console.log("Service worker active");
      }
    } catch (error) {
      console.error(`Registration failed with ${error}`);
    }
  }
};

// …

registerServiceWorker();
```

1. The `if`-block performs a feature detection test to make sure service workers are supported before trying to register one.
2. Next, we use the `ServiceWorkerContainer.register()` function to register the service worker for this site. The service worker code is in a JavaScript file residing inside our app (note this is the file's URL relative to the origin, not the JS file that references it.)
3. The `scope` parameter is optional, and can be used to specify the subset of your content that you want the service worker to control. In this case, we have specified `'/'`, which means all content under the app's origin. If you leave it out, it will default to this value anyway, but we specified it here for illustration purposes.

This registers a service worker, which runs in a worker context, and therefore has no DOM access.

A single service worker can control many pages. Each time a page within your scope is loaded, the service worker is installed against that page and operates on it. Bear in mind therefore that you need to be careful with global variables in the service worker script: each page doesn't get its own unique worker.

**Note:** One great thing about service workers is that if you use feature detection like we've shown above, browsers that don't support service workers can just use your app online in the normal expected fashion.

#### Why is my service worker failing to register?

This could be for the following reasons:

* You are not running your application through HTTPS.
* The path to your service worker file is not written correctly — it needs to be written relative to the origin, not your app's root directory. In our example, the worker is at `https://bncb2v.csb.app/sw.js`, and the app's root is `https://bncb2v.csb.app/`. But the path needs to be written as `/sw.js`.
* It is also not allowed to point to a service worker of a different origin than that of your app.
* The service worker will only catch requests from clients under the service worker's scope.
* The max scope for a service worker is the location of the worker (in other words if the script `sw.js` is located in `/js/sw.js`, it can only control URLs under `/js/` by default). A list of max scopes for that worker can be specified with the `Service-Worker-Allowed` header.
* In Firefox, Service Worker APIs are hidden and cannot be used when the user is in private browsing mode, or when history is disabled, or if cookies are cleared when Firefox is closed.
* In Chrome, registration fails when the "Block all cookies (not recommended)" option is enabled.
### Install and activate: populating your cache

After your service worker is registered, the browser will attempt to install then activate the service worker for your page/site.

The `install` event is fired when an installation is successfully completed. The `install` event is generally used to populate your browser's offline caching capabilities with the assets you need to run your app offline. To do this, we use Service Worker's storage API — `cache` — a global object on the service worker that allows us to store assets delivered by responses, and keyed by their requests. This API works in a similar way to the browser's standard cache, but it is specific to your domain. The contents of the cache are kept until you clear them.

Here's how our service worker handles the `install` event:

```js
const addResourcesToCache = async (resources) => {
  const cache = await caches.open("v1");
  await cache.addAll(resources);
};

self.addEventListener("install", (event) => {
  event.waitUntil(
    addResourcesToCache([
      "/",
      "/index.html",
      "/style.css",
      "/app.js",
      "/image-list.js",
      "/star-wars-logo.jpg",
      "/gallery/bountyHunters.jpg",
      "/gallery/myLittleVader.jpg",
      "/gallery/snowTroopers.jpg",
    ]),
  );
});
```

1. Here we add an `install` event listener to the service worker (hence `self`), and then chain a `ExtendableEvent.waitUntil()` method onto the event — this ensures that the service worker will not install until the code inside `waitUntil()` has successfully occurred.
2. Inside `addResourcesToCache()` we use the `caches.open()` method to create a new cache called `v1`, which will be version 1 of our site resources cache. Then we call a function `addAll()` on the created cache, which for its parameter takes an array of URLs to all the resources you want to cache. The URLs are relative to the worker's location.
3. If the promise is rejected, the installation fails, and the worker won't do anything. This is OK, as you can fix your code and then try again the next time registration occurs.
4. After a successful installation, the service worker activates. This doesn't have much of a distinct use the first time your service worker is installed/activated, but it means more when the service worker is updated (see the Updating your service worker section later on.)

**Note:** The Web Storage API (`localStorage`) works in a similar way to service worker cache, but it is synchronous, so not allowed in service workers.

**Note:** IndexedDB can be used inside a service worker for data storage if you require it.

### Custom responses to requests

Now you've got your site assets cached, you need to tell service workers to do something with the cached content. This is done with the `fetch` event.

1. A `fetch` event fires every time any resource controlled by a service worker is fetched, which includes the documents inside the specified scope, and any resources referenced in those documents (for example if `index.html` makes a cross-origin request to embed an image, that still goes through its service worker.)
2. You can attach a `fetch` event listener to the service worker, then call the `respondWith()` method on the event to hijack our HTTP responses and update them with your own content.

```js
self.addEventListener("fetch", (event) => {
  event.respondWith(/\* custom content goes here \*/);
});
```

3. We could start by responding with the resource whose URL matches that of the network request, in each case:

```js
self.addEventListener("fetch", (event) => {
  event.respondWith(caches.match(event.request));
});
```

`caches.match(event.request)` allows us to match each resource requested from the network with the equivalent resource available in the cache, if there is a matching one available. The matching is done via URL and various headers, just like with normal HTTP requests.

![Fetch event diagram](/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers/sw-fetch.svg)

Recovering failed requests
--------------------------

So `caches.match(event.request)` is great when there is a match in the service worker cache, but what about cases when there isn't a match? If we didn't provide any kind of failure handling, our promise would resolve with `undefined` and we wouldn't get anything returned.

After testing the response from the cache, we can fall back on a regular network request:

```js
const cacheFirst = async (request) => {
  const responseFromCache = await caches.match(request);
  if (responseFromCache) {
    return responseFromCache;
  }
  return fetch(request);
};

self.addEventListener("fetch", (event) => {
  event.respondWith(cacheFirst(event.request));
});
```

If the resources aren't in the cache, they are requested from the network.

Using a more elaborate strategy, we could not only request the resource from the network, but also save it into the cache so that later requests for that resource could be retrieved offline too. This would mean that if extra images were added to the Star Wars gallery, our app could automatically grab them and cache them. The following snippet implements such a strategy:

```js
const putInCache = async (request, response) => {
  const cache = await caches.open("v1");
  await cache.put(request, response);
};

const cacheFirst = async (request) => {
  const responseFromCache = await caches.match(request);
  if (responseFromCache) {
    return responseFromCache;
  }
  const responseFromNetwork = await fetch(request);
  putInCache(request, responseFromNetwork.clone());
  return responseFromNetwork;
};

self.addEventListener("fetch", (event) => {
  event.respondWith(cacheFirst(event.request));
});
```

If the request URL is not available in the cache, we request the resource from the network request with `await fetch(request)`. After that, we put a clone of the response into the cache. The `putInCache()` function uses `caches.open('v1')` and `cache.put()` to add the resource to the cache. The original response is returned to the browser to be given to the page that called it.

Cloning the response is necessary because request and response streams can only be read once. In order to return the response to the browser and put it in the cache we have to clone it. So the original gets returned to the browser and the clone gets sent to the cache. They are each read once.

What might look a bit weird is that the promise returned by `putInCache()` is not awaited. But the reason is that we don't want to wait until the response clone has been added to the cache before returning a response.

The only trouble we have now is that if the request doesn't match anything in the cache, and the network is not available, our request will still fail. Let's provide a default fallback so that whatever happens, the user will at least get something:

```js
const putInCache = async (request, response) => {
  const cache = await caches.open("v1");
  await cache.put(request, response);
};

const cacheFirst = async ({ request, fallbackUrl }) => {
  // First try to get the resource from the cache
  const responseFromCache = await caches.match(request);
  if (responseFromCache) {
    return responseFromCache;
  }

  // Next try to get the resource from the network
  try {
    const responseFromNetwork = await fetch(request);
    // response may be used only once
    // we need to save clone to put one copy in cache
    // and serve second one
    putInCache(request, responseFromNetwork.clone());
    return responseFromNetwork;
  } catch (error) {
    const fallbackResponse = await caches.match(fallbackUrl);
    if (fallbackResponse) {
      return fallbackResponse;
    }
    // when even the fallback response is not available,
    // there is nothing we can do, but we must always
    // return a Response object
    return new Response("Network error happened", {
      status: 408,
      headers: { "Content-Type": "text/plain" },
    });
  }
};

self.addEventListener("fetch", (event) => {
  event.respondWith(
    cacheFirst({
      request: event.request,
      fallbackUrl: "/gallery/myLittleVader.jpg",
    }),
  );
});
```

We have opted for this fallback image because the only updates that are likely to fail are new images, as everything else is depended on for installation in the `install` event listener we saw earlier.

Service Worker navigation preload
---------------------------------

If enabled, the navigation preload feature starts downloading resources as soon as the fetch request is made, and in parallel with service worker activation. This ensures that download starts immediately on navigation to a page, rather than having to wait until the service worker is activated. That delay happens relatively rarely, but is unavoidable when it does happen, and may be significant.

First the feature must be enabled during service worker activation, using `registration.navigationPreload.enable()`:

```js
self.addEventListener("activate", (event) => {
  event.waitUntil(self.registration?.navigationPreload.enable());
});
```

Then use `event.preloadResponse` to wait for the preloaded resource to finish downloading in the `fetch` event handler.

Continuing the example from the previous sections, we insert the code to wait for the preloaded resource after the cache check, and before fetching from the network if that doesn't succeed.

The new process is:

1. Check cache
2. Wait on `event.preloadResponse`, which is passed as `preloadResponsePromise` to the `cacheFirst()` function. Cache the result if it returns.
3. If neither of these are defined then we go to the network.

```js
const addResourcesToCache = async (resources) => {
  const cache = await caches.open("v1");
  await cache.addAll(resources);
};

const putInCache = async (request, response) => {
  const cache = await caches.open("v1");
  await cache.put(request, response);
};

const cacheFirst = async ({ request, preloadResponsePromise, fallbackUrl }) => {
  // First try to get the resource from the cache
  const responseFromCache = await caches.match(request);
  if (responseFromCache) {
    return responseFromCache;
  }

  // Next try to use (and cache) the preloaded response, if it's there
  const preloadResponse = await preloadResponsePromise;
  if (preloadResponse) {
    console.info("using preload response", preloadResponse);
    putInCache(request, preloadResponse.clone());
    return preloadResponse;
  }

  // Next try to get the resource from the network
  try {
    const responseFromNetwork = await fetch(request);
    // response may be used only once
    // we need to save clone to put one copy in cache
    // and serve second one
    putInCache(request, responseFromNetwork.clone());
    return responseFromNetwork;
  } catch (error) {
    const fallbackResponse = await caches.match(fallbackUrl);
    if (fallbackResponse) {
      return fallbackResponse;
    }
    // when even the fallback response is not available,
    // there is nothing we can do, but we must always
    // return a Response object
    return new Response("Network error happened", {
      status: 408,
      headers: { "Content-Type": "text/plain" },
    });
  }
};

// Enable navigation preload
const enableNavigationPreload = async () => {
  if (self.registration.navigationPreload) {
    await self.registration.navigationPreload.enable();
  }
};

self.addEventListener("activate", (event) => {
  event.waitUntil(enableNavigationPreload());
});

self.addEventListener("install", (event) => {
  event.waitUntil(
    addResourcesToCache([
      "/",
      "/index.html",
      "/style.css",
      "/app.js",
      "/image-list.js",
      "/star-wars-logo.jpg",
      "/gallery/bountyHunters.jpg",
      "/gallery/myLittleVader.jpg",
      "/gallery/snowTroopers.jpg",
    ]),
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    cacheFirst({
      request: event.request,
      preloadResponsePromise: event.preloadResponse,
      fallbackUrl: "/gallery/myLittleVader.jpg",
    }),
  );
});
```

Note that in this example we download and cache the same data for the resource whether it is downloaded "normally" or preloaded. You can instead choose to download and cache a different resource on preload. For more information see `NavigationPreloadManager` > Custom responses.

Updating your service worker
----------------------------

If your service worker has previously been installed, but then a new version of the worker is available on refresh or page load, the new version is installed in the background, but not yet activated. It is only activated when there are no longer any pages loaded that are still using the old service worker. As soon as there are no more such pages still loaded, the new service worker activates.

**Note:** It is possible to bypass this by using `Clients.claim()`.

You'll want to update your `install` event listener in the new service worker to something like this (notice the new version number):

```js
const addResourcesToCache = async (resources) => {
  const cache = await caches.open("v2");
  await cache.addAll(resources);
};

self.addEventListener("install", (event) => {
  event.waitUntil(
    addResourcesToCache([
      "/",
      "/index.html",
      "/style.css",
      "/app.js",
      "/image-list.js",

      // …

      // include other new resources for the new version…
    ]),
  );
});
```

While the service worker is being installed, the previous version is still responsible for fetches. The new version is installing in the background. We are calling the new cache `v2`, so the previous `v1` cache isn't disturbed.

When no pages are using the previous version, the new worker activates and becomes responsible for fetches.

### Deleting old caches

As we saw in the last section, when you update a service worker to a new version, you'll create a new cache in its `install` event handler. While there are open pages that are controlled by the previous version of the worker, you need to keep both caches, because the previous version needs its version of the cache. You can use the `activate` event to remove data from the previous caches.

Promises passed into `waitUntil()` will block other events until completion, so you can rest assured that your clean-up operation will have completed by the time you get your first `fetch` event on the new service worker.

```js
const deleteCache = async (key) => {
  await caches.delete(key);
};

const deleteOldCaches = async () => {
  const cacheKeepList = ["v2"];
  const keyList = await caches.keys();
  const cachesToDelete = keyList.filter((key) => !cacheKeepList.includes(key));
  await Promise.all(cachesToDelete.map(deleteCache));
};

self.addEventListener("activate", (event) => {
  event.waitUntil(deleteOldCaches());
});
```

Developer tools
---------------

* Chrome
* Firefox
    + The "Forget about this site" button, available in Firefox's toolbar customization options, can be used to clear service workers and their caches.
* Edge
See also
--------

* Promises
* Using web workers


OVR_multiview2: framebufferTextureMultiviewOVR() method - Web APIs

OVR\_multiview2: framebufferTextureMultiviewOVR() method
========================================================

 The **`OVR_multiview2.framebufferTextureMultiviewOVR()`**
 method of the WebGL API attaches a multiview
 texture to a `WebGLFramebuffer`.

Syntax
------

```js
framebufferTextureMultiviewOVR(target, attachment, texture, level, baseViewIndex, numViews)
```

### Parameters

`target`

A `WebGL_API.Types` specifying the binding point (target). Possible values:

`gl.FRAMEBUFFER`

 Collection buffer data storage of color, alpha,
 depth and stencil buffers used to render an image.

`gl.DRAW_FRAMEBUFFER`

 Equivalent to `gl.FRAMEBUFFER`.
 Used as a destination for drawing, rendering, clearing, and writing operations.

`gl.READ_FRAMEBUFFER`

Used as a source for reading operations.

`attachment`

 A `WebGL_API.Types` specifying the attachment point for the
 `texture`. Possible values:

* `gl.COLOR_ATTACHMENT0`: Attaches the texture to the framebuffer's
 color buffer.
* `gl.DEPTH_ATTACHMENT`: Attaches the texture to the framebuffer's
 depth buffer.
* `gl.STENCIL_ATTACHMENT`: Attaches the texture to the framebuffer's
 stencil buffer.
* `gl.DEPTH_STENCIL_ATTACHMENT`: depth and stencil buffer.
* `gl.COLOR_ATTACHMENT1 gl.COLOR_ATTACHMENT2 gl.COLOR_ATTACHMENT3 gl.COLOR_ATTACHMENT4 gl.COLOR_ATTACHMENT5 gl.COLOR_ATTACHMENT6 gl.COLOR_ATTACHMENT7 gl.COLOR_ATTACHMENT8 gl.COLOR_ATTACHMENT9 gl.COLOR_ATTACHMENT10 gl.COLOR_ATTACHMENT11 gl.COLOR_ATTACHMENT12 gl.COLOR_ATTACHMENT13 gl.COLOR_ATTACHMENT14 gl.COLOR_ATTACHMENT15`
 When using the `WEBGL_draw_buffers` extension:
    + `ext.COLOR_ATTACHMENT0_WEBGL` (same as
     `gl.COLOR_ATTACHMENT0`)
     `ext.COLOR_ATTACHMENT1_WEBGL ext.COLOR_ATTACHMENT2_WEBGL ext.COLOR_ATTACHMENT3_WEBGL ext.COLOR_ATTACHMENT4_WEBGL ext.COLOR_ATTACHMENT5_WEBGL ext.COLOR_ATTACHMENT6_WEBGL ext.COLOR_ATTACHMENT7_WEBGL ext.COLOR_ATTACHMENT8_WEBGL ext.COLOR_ATTACHMENT9_WEBGL ext.COLOR_ATTACHMENT10_WEBGL ext.COLOR_ATTACHMENT11_WEBGL ext.COLOR_ATTACHMENT12_WEBGL ext.COLOR_ATTACHMENT13_WEBGL ext.COLOR_ATTACHMENT14_WEBGL ext.COLOR_ATTACHMENT15_WEBGL`

When using the `WEBGL_depth_texture` extension:

* `ext.DEPTH_STENCIL_ATTACHMENT`: Depth and stencil buffer data
 storage.

`texture`

A `WebGLTexture` object whose image to attach.

`level`

 A `WebGL_API.Types` specifying the mipmap level of the texture image to be
 attached. Must be 0.

`baseViewIndex`

 A `WebGL_API.Types` specifying the base view index of the framebuffer object
 attachment.

`numViews`

 A `WebGL_API.Types` specifying the number of views of the framebuffer object
 attachment.

### Return value

None (`undefined`).

### Exceptions

* A `gl.INVALID_ENUM` error is thrown if
    + `target` is not `gl.FRAMEBUFFER`.
    + `attachment` is not one of the accepted attachment points.
* A `gl.INVALID_VALUE` error is thrown if
    + `level` is not 0.
    + if `numViews` is less than one or more than
     `MAX_VIEWS_OVR`.
* A `gl.INVALID_OPERATION` error is thrown if `texture` isn't 0
 or the name of an existing texture object.
Examples
--------

```js
ext.framebufferTextureMultiviewOVR(
  gl.DRAW\_FRAMEBUFFER,
  gl.COLOR\_ATTACHMENT0,
  colorTex,
  0,
  0,
  2,
);
```

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

| Specification |
| --- |
| WebGL OVR\_multiview2 Extension Specification  |

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

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

See also
--------

* `OVR_multiview2`
* `WEBGL_depth_texture`
* `WEBGL_draw_buffers`


Using the Web Speech API - Web APIs

Using the Web Speech API
========================

 The Web Speech API provides two distinct areas of functionality — speech recognition, and speech synthesis (also known as text to speech, or tts) — which open up interesting new possibilities for accessibility, and control mechanisms. This article provides a simple introduction to both areas, along with demos.
Speech recognition
------------------

Speech recognition involves receiving speech through a device's microphone, which is then checked by a speech recognition service against a list of grammar (basically, the vocabulary you want to have recognized in a particular app.) When a word or phrase is successfully recognized, it is returned as a result (or list of results) as a text string, and further actions can be initiated as a result.

The Web Speech API has a main controller interface for this — `SpeechRecognition` — plus a number of closely-related interfaces for representing grammar, results, etc. Generally, the default speech recognition system available on the device will be used for the speech recognition — most modern OSes have a speech recognition system for issuing voice commands. Think about Dictation on macOS, Siri on iOS, Cortana on Windows 10, Android Speech, etc.

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

### Demo

To show simple usage of Web speech recognition, we've written a demo called Speech color changer. When the screen is tapped/clicked, you can say an HTML color keyword, and the app's background color will change to that color.

![The UI of an app titled Speech Color changer. It invites the user to tap the screen and say a color, and then it turns the background of the app that color. In this case it has turned the background red.](/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API/speech-color-changer.png)

To run the demo, navigate to the live demo URL in a supporting mobile browser (such as Chrome).

### HTML and CSS

The HTML and CSS for the app is really trivial. We have a title, instructions paragraph, and a div into which we output diagnostic messages.

```html
<h1>Speech color changer</h1>
<p>Tap/click then say a color to change the background color of the app.</p>
<div>
  <p class="output"><em>…diagnostic messages</em></p>
</div>
```

The CSS provides a very simple responsive styling so that it looks OK across devices.

### JavaScript

Let's look at the JavaScript in a bit more detail.

#### Prefixed properties

 Browsers currently support speech recognition with prefixed properties.
 Therefore at the start of our code we include these lines to allow for both prefixed properties and unprefixed versions that may be supported in future:

```js
const SpeechRecognition =
  window.SpeechRecognition || window.webkitSpeechRecognition;
const SpeechGrammarList =
  window.SpeechGrammarList || window.webkitSpeechGrammarList;
const SpeechRecognitionEvent =
  window.SpeechRecognitionEvent || window.webkitSpeechRecognitionEvent;
```

#### The grammar

The next part of our code defines the grammar we want our app to recognize. The following variable is defined to hold our grammar:

```js
const colors = [
  "aqua",
  "azure",
  "beige",
  "bisque",
  "black",
  "blue",
  "brown",
  "chocolate",
  "coral" /\* … \*/,
];
const grammar = `#JSGF V1.0; grammar colors; public <color> = ${colors.join(
 " | ",
)};`;
```

The grammar format used is JSpeech Grammar Format (**JSGF**) — you can find a lot more about it at the previous link to its spec. However, for now let's just run through it quickly:

* The lines are separated by semicolons, just like in JavaScript.
* The first line — `#JSGF V1.0;` — states the format and version used. This always needs to be included first.
* The second line indicates a type of term that we want to recognize. `public` declares that it is a public rule, the string in angle brackets defines the recognized name for this term (`color`), and the list of items that follow the equals sign are the alternative values that will be recognized and accepted as appropriate values for the term. Note how each is separated by a pipe character.
* You can have as many terms defined as you want on separate lines following the above structure, and include fairly complex grammar definitions. For this basic demo, we are just keeping things simple.

#### Plugging the grammar into our speech recognition

The next thing to do is define a speech recognition instance to control the recognition for our application. This is done using the `SpeechRecognition()` constructor. We also create a new speech grammar list to contain our grammar, using the `SpeechGrammarList()` constructor.

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

We add our `grammar` to the list using the `SpeechGrammarList.addFromString()` method. This accepts as parameters the string we want to add, plus optionally a weight value that specifies the importance of this grammar in relation of other grammars available in the list (can be from 0 to 1 inclusive.) The added grammar is available in the list as a `SpeechGrammar` object instance.

```js
speechRecognitionList.addFromString(grammar, 1);
```

We then add the `SpeechGrammarList` to the speech recognition instance by setting it to the value of the `SpeechRecognition.grammars` property. We also set a few other properties of the recognition instance before we move on:

* `SpeechRecognition.continuous`: Controls whether continuous results are captured (`true`), or just a single result each time recognition is started (`false`).
* `SpeechRecognition.lang`: Sets the language of the recognition. Setting this is good practice, and therefore recommended.
* `SpeechRecognition.interimResults`: Defines whether the speech recognition system should return interim results, or just final results. Final results are good enough for this simple demo.
* `SpeechRecognition.maxAlternatives`: Sets the number of alternative potential matches that should be returned per result. This can sometimes be useful, say if a result is not completely clear and you want to display a list if alternatives for the user to choose the correct one from. But it is not needed for this simple demo, so we are just specifying one (which is actually the default anyway.)

```js
recognition.grammars = speechRecognitionList;
recognition.continuous = false;
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 1;
```

#### Starting the speech recognition

After grabbing references to the output `<div>` and the HTML element (so we can output diagnostic messages and update the app background color later on), we implement an onclick handler so that when the screen is tapped/clicked, the speech recognition service will start. This is achieved by calling `SpeechRecognition.start()`. The `forEach()` method is used to output colored indicators showing what colors to try saying.

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

let colorHTML = "";
colors.forEach((color, i) => {
  console.log(color, i);
  colorHTML += `<span style="background-color:${color};"> ${color} </span>`;
});
hints.innerHTML = `Tap or click then say a color to change the background color of the app. Try ${colorHTML}.`;

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

#### Receiving and handling results

Once the speech recognition is started, there are many event handlers that can be used to retrieve results, and other pieces of surrounding information (see the `SpeechRecognition` events.) The most common one you'll probably use is the `result` event, which is fired once a successful result is received:

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

The second line here is a bit complex-looking, so let's explain it step by step. The `SpeechRecognitionEvent.results` property returns a `SpeechRecognitionResultList` object containing `SpeechRecognitionResult` objects. It has a getter so it can be accessed like an array — so the first `[0]` returns the `SpeechRecognitionResult` at position 0. Each `SpeechRecognitionResult` object contains `SpeechRecognitionAlternative` objects that contain individual recognized words. These also have getters so they can be accessed like arrays — the second `[0]` therefore returns the `SpeechRecognitionAlternative` at position 0. We then return its `transcript` property to get a string containing the individual recognized result as a string, set the background color to that color, and report the color recognized as a diagnostic message in the UI.

We also use the `speechend` event to stop the speech recognition service from running (using `SpeechRecognition.stop()`) once a single word has been recognized and it has finished being spoken:

```js
recognition.onspeechend = () => {
  recognition.stop();
};
```

#### Handling errors and unrecognized speech

The last two handlers are there to handle cases where speech was recognized that wasn't in the defined grammar, or an error occurred. The `nomatch` event seems to be supposed to handle the first case mentioned, although note that at the moment it doesn't seem to fire correctly; it just returns whatever was recognized anyway:

```js
recognition.onnomatch = (event) => {
  diagnostic.textContent = "I didn't recognize that color.";
};
```

The `error` event handles cases where there is an actual error with the recognition successfully — the `SpeechRecognitionErrorEvent.error` property contains the actual error returned:

```js
recognition.onerror = (event) => {
  diagnostic.textContent = `Error occurred in recognition: ${event.error}`;
};
```

Speech synthesis
----------------

Speech synthesis (aka text-to-speech, or TTS) involves receiving synthesizing text contained within an app to speech, and playing it out of a device's speaker or audio output connection.

The Web Speech API has a main controller interface for this — `SpeechSynthesis` — plus a number of closely-related interfaces for representing text to be synthesized (known as utterances), voices to be used for the utterance, etc. Again, most OSes have some kind of speech synthesis system, which will be used by the API for this task as available.

### Demo

To show simple usage of Web speech synthesis, we've provided a demo called Speak easy synthesis. This includes a set of form controls for entering text to be synthesized, and setting the pitch, rate, and voice to use when the text is uttered. After you have entered your text, you can press `Enter`/`Return` to hear it spoken.

![UI of an app called speak easy synthesis. It has an input field in which to input text to be synthesized, slider controls to change the rate and pitch of the speech, and a drop down menu to choose between different voices.](/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API/speak-easy-synthesis.png)

To run the demo, navigate to the live demo URL in a supporting mobile browser.

### HTML and CSS

The HTML and CSS are again pretty trivial, containing a title, some instructions for use, and a form with some simple controls. The `<select>` element is initially empty, but is populated with `<option>`s via JavaScript (see later on.)

```html
<h1>Speech synthesizer</h1>

<p>
  Enter some text in the input below and press return to hear it. change voices
  using the dropdown menu.
</p>

<form>
  <input type="text" class="txt" />
  <div>
    <label for="rate">Rate</label
 ><input type="range" min="0.5" max="2" value="1" step="0.1" id="rate" />
    <div class="rate-value">1</div>
    <div class="clearfix"></div>
  </div>
  <div>
    <label for="pitch">Pitch</label
 ><input type="range" min="0" max="2" value="1" step="0.1" id="pitch" />
    <div class="pitch-value">1</div>
    <div class="clearfix"></div>
  </div>
  <select></select>
</form>
```

### JavaScript

Let's investigate the JavaScript that powers this app.

#### Setting variables

First of all, we capture references to all the DOM elements involved in the UI, but more interestingly, we capture a reference to `Window.speechSynthesis`. This is API's entry point — it returns an instance of `SpeechSynthesis`, the controller interface for web speech synthesis.

```js
const synth = window.speechSynthesis;

const inputForm = document.querySelector("form");
const inputTxt = document.querySelector(".txt");
const voiceSelect = document.querySelector("select");

const pitch = document.querySelector("#pitch");
const pitchValue = document.querySelector(".pitch-value");
const rate = document.querySelector("#rate");
const rateValue = document.querySelector(".rate-value");

const voices = [];
```

#### Populating the select element

To populate the `<select>` element with the different voice options the device has available, we've written a `populateVoiceList()` function. We first invoke `SpeechSynthesis.getVoices()`, which returns a list of all the available voices, represented by `SpeechSynthesisVoice` objects. We then loop through this list — for each voice we create an `<option>` element, set its text content to display the name of the voice (grabbed from `SpeechSynthesisVoice.name`), the language of the voice (grabbed from `SpeechSynthesisVoice.lang`), and `-- DEFAULT` if the voice is the default voice for the synthesis engine (checked by seeing if `SpeechSynthesisVoice.default` returns `true`.)

We also create `data-` attributes for each option, containing the name and language of the associated voice, so we can grab them easily later on, and then append the options as children of the select.

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

  for (const voice of voices) {
    const option = document.createElement("option");
    option.textContent = `${voice.name} (${voice.lang})`;

    if (voice.default) {
      option.textContent += " — DEFAULT";
    }

    option.setAttribute("data-lang", voice.lang);
    option.setAttribute("data-name", voice.name);
    voiceSelect.appendChild(option);
  }
}
```

 Older browser don't support the `voiceschanged` event, and just return a list of voices when `SpeechSynthesis.getVoices()` is fired.
 While on others, such as Chrome, you have to wait for the event to fire before populating the list.
 To allow for both cases, we run the function as shown below:

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

#### Speaking the entered text

Next, we create an event handler to start speaking the text entered into the text field. We are using an onsubmit handler on the form so that the action happens when `Enter`/`Return` is pressed. We first create a new `SpeechSynthesisUtterance()` instance using its constructor — this is passed the text input's value as a parameter.

Next, we need to figure out which voice to use. We use the `HTMLSelectElement` `selectedOptions` property to return the currently selected `<option>` element. We then use this element's `data-name` attribute, finding the `SpeechSynthesisVoice` object whose name matches this attribute's value. We set the matching voice object to be the value of the `SpeechSynthesisUtterance.voice` property.

Finally, we set the `SpeechSynthesisUtterance.pitch` and `SpeechSynthesisUtterance.rate` to the values of the relevant range form elements. Then, with all necessary preparations made, we start the utterance being spoken by invoking `SpeechSynthesis.speak()`, passing it the `SpeechSynthesisUtterance` instance as a parameter.

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

  const utterThis = new SpeechSynthesisUtterance(inputTxt.value);
  const selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
  for (const voice of voices) {
    if (voice.name === selectedOption) {
      utterThis.voice = voice;
    }
  }
  utterThis.pitch = pitch.value;
  utterThis.rate = rate.value;
  synth.speak(utterThis);
```

In the final part of the handler, we include an `pause` event to demonstrate how `SpeechSynthesisEvent` can be put to good use. When `SpeechSynthesis.pause()` is invoked, this returns a message reporting the character number and name that the speech was paused at.

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

Finally, we call blur() on the text input. This is mainly to hide the keyboard on Firefox OS.

```js
  inputTxt.blur();
}
```

#### Updating the displayed pitch and rate values

The last part of the code updates the `pitch`/`rate` values displayed in the UI, each time the slider positions are moved.

```js
pitch.onchange = () => {
  pitchValue.textContent = pitch.value;
};

rate.onchange = () => {
  rateValue.textContent = rate.value;
};
```


CSS: registerProperty() static method - Web APIs

CSS: registerProperty() static method
=====================================

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

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

* Learn more
* See full compatibility
* Report feedback

 The **`CSS.registerProperty()`** static method registers
 `custom properties`, allowing for property type checking, default
 values, and properties that do or do not inherit their value.

 Registering a custom property allows you to tell the browser how the custom property
 should behave; what types are allowed, whether the custom property inherits its value,
 and what the default value of the custom property is.

Syntax
------

```js
CSS.registerProperty(PropertyDefinition)
```

### Parameters

 A `PropertyDefinition` dictionary object, which can contain the following
 members:

`name`

 A string representing the
 name of the property being defined.

`syntax` Optional

 A string representing
 the expected syntax of the defined property. Defaults to `"*"`.

`inherits`

 A boolean value defining whether the defined property should be inherited
 (`true`), or not (`false`). Defaults to `false`.

`initialValue` Optional

 A string representing
 the initial value of the defined property.

### Return value

`undefined`.

### Exceptions

`InvalidModificationError` `DOMException`

The given `name` has already been registered.

`SyntaxError` `DOMException`

 The given `name` isn't a valid custom property name (starts with two
 dashes, e.g. `--foo`).

`TypeError`

 The required `name` and/or `inherits` dictionary members were
 not provided.

Examples
--------

 The following will register a `custom property`,
 `--my-color`, using `registerProperty()`, as a color, give it a
 default value, and have it not inherit its value:

```js
window.CSS.registerProperty({
  name: "--my-color",
  syntax: "<color>",
  inherits: false,
  initialValue: "#c0ffee",
});
```

 In this example, the custom property `--my-color` has been registered using
 the syntax `<color>`. We can now use that property to transition a
 gradient on hover or focus. Notice that with the registered property the transition
 works, but that it doesn't with the unregistered property!

```css
.registered {
  --my-color: #c0ffee;
  background-image: linear-gradient(to right, #fff, var(--my-color));
  transition: --my-color 1s ease-in-out;
}

.registered:hover,
.registered:focus {
  --my-color: #b4d455;
}

.unregistered {
  --unregistered: #c0ffee;
  background-image: linear-gradient(to right, #fff, var(--unregistered));
  transition: --unregistered 1s ease-in-out;
}

.unregistered:hover,
.unregistered:focus {
  --unregistered: #b4d455;
}
button {
  font-size: 3vw;
}
```

We can add these styles to some buttons:

```html
<button class="registered">Background Registered</button>
<button class="unregistered">Background Not Registered</button>
```

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

| Specification |
| --- |
| CSS Properties and Values API Level 1 # the-registerproperty-function |

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

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

See also
--------

* Using the CSS properties and values API
* `CSS`
* `CSS.supports()`
* `CSS.escape()`
* `CSS factory functions`
* CSS `@property`


CSS: highlights static property - Web APIs

CSS: highlights static property
===============================

The static, read-only **`highlights`** property of the `CSS` interface provides access to the `HighlightRegistry` used to style arbitrary text ranges using the CSS Custom Highlight API.

Value
-----

The `HighlightRegistry` object.

Examples
--------

The following example demonstrates creating multiple text ranges, then creating a `Highlight` object for them, registering this highlight in the `HighlightRegistry`, and finally styling the text ranges using the `::highlight()` pseudo-element.

```js
const parentNode = document.getElementById("foo");

const range1 = new Range();
range1.setStart(parentNode, 10);
range1.setEnd(parentNode, 20);

const range2 = new Range();
range2.setStart(parentNode, 40);
range2.setEnd(parentNode, 60);

const myCustomHighlight = new Highlight(range1, range2);

CSS.highlights.set("my-custom-highlight", myCustomHighlight);
```

```css
::highlight(my-custom-highlight) {
  background-color: yellow;
  color: black;
}
```

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

| Specification |
| --- |
| CSS Custom Highlight API Module Level 1 # dom-css-highlights |

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

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

See also
--------

* The CSS Custom Highlight API
* CSS Custom Highlight API: The Future of Highlighting Text Ranges on the Web


CSS: escape() static method - Web APIs

CSS: escape() static method
===========================

 The **`CSS.escape()`** static method returns a
 string containing the escaped string passed as parameter, mostly for
 use as part of a CSS selector.

Syntax
------

```js
CSS.escape(str)
```

### Parameters

`str`

The string to be escaped.

### Return value

The escaped string.

Examples
--------

### Basic results

```js
CSS.escape(".foo#bar"); // "\\.foo\\#bar"
CSS.escape("()[]{}"); // "\\(\\)\\[\\]\{\}"
CSS.escape('--a'); // "--a"
CSS.escape(0); // "\\30 ", the Unicode code point of '0' is 30
CSS.escape('\0'); // "\ufffd", the Unicode REPLACEMENT CHARACTER
```

### In context uses

 To escape a string for use as part of a selector, the `escape()` method can
 be used:

```js
const element = document.querySelector(`#${CSS.escape(id)} > img`);
```

 The `escape()` method can also be used for escaping strings, although it
 escapes characters that don't strictly need to be escaped:

```js
const element = document.querySelector(`a[href="#${CSS.escape(fragment)}"]`);
```

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

| Specification |
| --- |
| CSS Object Model (CSSOM) # the-css.escape()-method |

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

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

See also
--------

* The `CSS` interface where this static method resides.
* A polyfill for the CSS.escape


CSS numeric factory functions - Web APIs

CSS numeric factory functions
=============================

 The **CSS numeric factory
functions**, such as `CSS.em()` and
 `CSS.turn()` are methods that return CSSUnitValues with the value being
 the numeric argument and the unit being the name of the method used. These
 functions create new numeric values less verbosely than using the
 `CSSUnitValue()` constructor.

Syntax
------

```js
CSS.number(number)
CSS.percent(number)

// <length>
CSS.em(number)
CSS.ex(number)
CSS.ch(number)
CSS.ic(number)
CSS.rem(number)
CSS.lh(number)
CSS.rlh(number)
CSS.vw(number)
CSS.vh(number)
CSS.vi(number)
CSS.vb(number)
CSS.vmin(number)
CSS.vmax(number)
CSS.cm(number)
CSS.mm(number)
CSS.Q(number)
CSS.in(number)
CSS.pt(number)
CSS.pc(number)
CSS.px(number)

// <angle>
CSS.deg(number)
CSS.grad(number)
CSS.rad(number)
CSS.turn(number)

// <time>
CSS.s(number)
CSS.ms(number)

// <frequency>
CSS.Hz(number)
CSS.kHz(number)

// <resolution>
CSS.dpi(number)
CSS.dpcm(number)
CSS.dppx(number)

// <flex>
CSS.fr(number)
```

Examples
--------

 We use the `CSS.vmax()` numeric factory function to create a
 `CSSUnitValue`:

```js
const height = CSS.vmax(50);

console.log(height); // CSSUnitValue {value: 50, unit: "vmax"}
console.log(height.value); // 50
console.log(height.unit); // vmax
```

 In this example, we set the margin on our element using the `CSS.px()`
 factory function:

```js
myElement.attributeStyleMap.set("margin", CSS.px(40));
const currentMargin = myElement.attributeStyleMap.get("margin");
console.log(currentMargin.value, currentMargin.unit); // 40, 'px'
```

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

| Specification |
| --- |
| CSS Object Model (CSSOM) # namespacedef-css |

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

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

See also
--------

* `CSSUnitValue()`


CSS: supports() static method - Web APIs

CSS: supports() static method
=============================

 The **`CSS.supports()`** static method returns a boolean value
 indicating if the browser supports a given CSS feature, or not.

Syntax
------

```js
CSS.supports(propertyName, value)
CSS.supports(supportCondition)
```

### Parameters

 There are two distinct sets of parameters. The first one allows to test the support of
 a pair *property-value*:

`propertyName`

A string containing the name of the CSS property to check.

`value`

A string containing the value of the CSS property to check.

 The second syntax takes one parameter matching the condition of
 `@supports`:

`supportCondition`

A string containing the condition to check.

### Return value

`true` if the browser supports the rule, otherwise `false`.

Examples
--------

```js
result = CSS.supports("text-decoration-style", "blink");
result = CSS.supports("display: flex");
result = CSS.supports("(--foo: red)");

result = CSS.supports(
  "(transform-style: preserve) or (-moz-transform-style: preserve) or (-webkit-transform-style: preserve)",
);

// result is true or false
```

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

| Specification |
| --- |
| CSS Conditional Rules Module Level 3 # ref-for-dom-css-supports |

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

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

See also
--------

* The `@supports` at-rule that allows for the same functionality but in a
 declarative way.
* The `CSSSupportsRule` CSSOM class allowing to manipulate
 `@supports` at-rules.


CSS: paintWorklet static property - Web APIs

CSS: paintWorklet static property
=================================

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

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

 The static, read-only **`paintWorklet`** property of the `CSS` interface provides access to the
 paint worklet, which programmatically generates an image where a CSS
 property expects a file.

Value
-----

The associated `Worklet` object.

Examples
--------

 The following example demonstrates loading a paint worklet from its js
 file and does so by feature detection.

```js
if ("paintWorklet" in CSS) {
  CSS.paintWorklet.addModule("checkerboard.js");
}
```

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

| Specification |
| --- |
| CSS Painting API Level 1 # ref-for-dom-css-paintworklet |

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

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

See also
--------

* CSS Painting API
* Houdini APIs


MediaQueryList: removeListener() method - Web APIs

MediaQueryList: removeListener() 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.

 The **`removeListener()`** method of the
 `MediaQueryList` interface removes a listener from the
 `MediaQueryListener`.

 In older browsers `MediaQueryList` did not yet inherit from `EventTarget`,
 so this method was provided as an alias of `EventTarget.removeEventListener()`.
 Use `removeEventListener()` instead of `removeListener()` if it is
 available in the browsers you need to support.

Syntax
------

```js
removeListener(func)
```

### Parameters

`func`

 A function or function reference representing the callback function you want to
 remove.

### Return value

None (`undefined`).

Examples
--------

```js
const paragraph = document.querySelector("p");
const mediaQueryList = window.matchMedia("(max-width: 600px)");

function screenTest(e) {
  if (e.matches) {
    /\* the viewport is 600 pixels wide or less \*/
    paragraph.textContent = "This is a narrow screen — 600px wide or less.";
    document.body.style.backgroundColor = "pink";
  } else {
    /\* the viewport is more than 600 pixels wide \*/
    paragraph.textContent = "This is a wide screen — more than 600px wide.";
    document.body.style.backgroundColor = "aquamarine";
  }
}

mediaQueryList.addListener(screenTest);

// Later on, when it is no longer needed
mediaQueryList.removeListener(screenTest);
```

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

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylist-removelistener |

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

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

See also
--------

* Media queries
* Using media queries from code
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


MediaQueryList: media property - Web APIs

MediaQueryList: media property
==============================

 The **`media`** read-only property of the
 `MediaQueryList` interface is a string representing a
 serialized media query.

Value
-----

A string representing a serialized media query.

Examples
--------

 This example runs the media query `(max-width: 600px)` and displays the
 value of the resulting `MediaQueryList`'s `media` property in a
 `<span>`.

### JavaScript

```js
let mql = window.matchMedia("(max-width: 600px)");

document.querySelector(".mq-value").innerText = mql.media;
```

 The JavaScript code passes the media query to match into `matchMedia()` to compile it, then sets the `<span>`'s
 `innerText` to the value of the result's
 `media` property.

### HTML

```html
<span class="mq-value"></span>
```

A simple `<span>` to receive the output.
```

.mq-value {
  font:
    18px arial,
    sans-serif;
  font-weight: bold;
  color: #88f;
  padding: 0.4em;
  border: 1px solid #dde;
}
```

### Result

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

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylist-media |

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

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

See also
--------

* Media queries
* Using media queries from code
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


MediaQueryList: matches property - Web APIs

MediaQueryList: matches property
================================

 The **`matches`** read-only property of the
 `MediaQueryList` interface is a boolean value that returns
 `true` if the `document` currently matches the media query list,
 or `false` if not.

 You can be notified when the value of `matches` changes by watching for the
 `change` event to be fired at the
 `MediaQueryList`.

Value
-----

 A boolean value that is `true` if the `document`
 currently matches the media query list; otherwise, it's `false`.

Examples
--------

 This example detects viewport orientation changes by creating a media query using the
 `orientation` media
 feature:

```js
const mql = window.matchMedia("(orientation:landscape)");
mql.addEventListener("change", (event) => {
  if (event.matches) {
    console.log("Now in landscape orientation");
  } else {
    console.log("Now in portrait orientation");
  }
});
```

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

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylist-matches |

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

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

See also
--------

* Media queries
* Using media queries from code
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


MediaQueryList: change event - Web APIs

MediaQueryList: change event
============================

The **`change`** event of the `MediaQueryList` interface fires when the status of media query support changes.

Syntax
------

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

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

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

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

A `MediaQueryListEvent`. Inherits from `Event`.

Event

MediaQueryListEventEvent properties
----------------

*The `MediaQueryListEvent` interface inherits properties from its parent interface, `Event`.*

`MediaQueryListEvent.matches` Read only

A boolean value that is `true` if the `document` currently matches the media query list, or `false` if not.

`MediaQueryListEvent.media` Read only

A string representing a serialized media query.

Example
-------

```js
const mql = window.matchMedia("(max-width: 600px)");

mql.onchange = (e) => {
  if (e.matches) {
    /\* the viewport is 600 pixels wide or less \*/
    console.log("This is a narrow screen — less than 600px wide.");
  } else {
    /\* the viewport is more than 600 pixels wide \*/
    console.log("This is a wide screen — more than 600px wide.");
  }
};
```

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

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylist-onchange |

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

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

See also
--------

* Media queries
* Using media queries from code
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


MediaQueryList: addListener() method - Web APIs

MediaQueryList: addListener() 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.

 The deprecated **`addListener()`** method of the
 `MediaQueryList` interface adds a listener to the
 `MediaQueryListener` that will run a custom callback function in response to
 the media query status changing.

 In older browsers `MediaQueryList` did not yet inherit from `EventTarget`,
 so this method was provided as an alias of `EventTarget.addEventListener()`.
 Use `addEventListener()` instead of `addListener()` if it is
 available in the browsers you need to support.

Syntax
------

```js
addListener(func)
```

### Parameters

`func`

 A function or function reference representing the callback function you want to run
 when the media query status changes.

### Return value

None (`undefined`).

Examples
--------

```js
const paragraph = document.querySelector("p");
const mediaQueryList = window.matchMedia("(max-width: 600px)");

function screenTest(e) {
  if (e.matches) {
    /\* the viewport is 600 pixels wide or less \*/
    paragraph.textContent = "This is a narrow screen — 600px wide or less.";
    document.body.style.backgroundColor = "pink";
  } else {
    /\* the viewport is more than 600 pixels wide \*/
    paragraph.textContent = "This is a wide screen — more than 600px wide.";
    document.body.style.backgroundColor = "aquamarine";
  }
}

mediaQueryList.addListener(screenTest);
```

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

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylist-addlistener |

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

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

See also
--------

* Media queries
* Using media queries from code
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


LaunchParams: files property - Web APIs

LaunchParams: files property
============================

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

The **`files`** read-only property of the `LaunchParams` interface returns an array of `FileSystemHandle` objects representing any files passed along with the launch navigation via the `POST` method.

Value
-----

A read-only array of `FileSystemHandle` objects.

Examples
--------

```js
if ("launchQueue" in window) {
  window.launchQueue.setConsumer((launchParams) => {
    if (launchParams.files) {
      const files = launchParams.files;
      for (file in files) {
        // Do stuff with file handles
      }
    }
  });
}
```

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

| Specification |
| --- |
| Web App Launch Handler API # ref-for-dom-launchparams-files-1 |

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

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

See also
--------

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


LaunchParams: targetURL property - Web APIs

LaunchParams: targetURL property
================================

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

The **`targetURL`** read-only property of the `LaunchParams` interface returns the target URL of the associated web app launch.

Value
-----

A string.

Examples
--------

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

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

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

| Specification |
| --- |
| Web App Launch Handler API # ref-for-dom-launchparams-targeturl-7 |

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

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

See also
--------

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


ScrollTimeline: axis property - Web APIs

ScrollTimeline: axis property
=============================

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

 The **`axis`** read-only property of the
 `ScrollTimeline` interface returns an enumerated value representing the scroll axis that is driving the progress of the timeline.

Value
-----

An enumerated value. Possible values are:

`"block"`

The scrollbar on the block axis of the scroll container, which is the axis in the direction perpendicular to the flow of text within a line. For horizontal writing modes, such as standard English, this is the same as `"y"`, while for vertical writing modes, it is the same as `"x"`.

`"inline"`

The scrollbar on the inline axis of the scroll container, which is the axis in the direction parallel to the flow of text in a line. For horizontal writing modes, this is the same as `"x"`, while for vertical writing modes, this is the same as `"y"`.

`"y"`

The scrollbar on the vertical axis of the scroll container.

`"x"`

The scrollbar on the horizontal axis of the scroll container.

Examples
--------

See the main `ScrollTimeline` page for an example.

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

| Specification |
| --- |
| Scroll-driven Animations # dom-scrolltimeline-axis |

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

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

See also
--------

* `ScrollTimeline`
* `AnimationTimeline`, `ViewTimeline`
* Web Animations API
* CSS scroll-driven animations


ScrollTimeline: ScrollTimeline() constructor - Web APIs

ScrollTimeline: ScrollTimeline() constructor
============================================

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

The **`ScrollTimeline()`** constructor creates a new `ScrollTimeline` object instance.

Syntax
------

```js
new ScrollTimeline(options)
```

### Parameters

`options`

An object that can contain the following properties:

`source`

A reference to an `Element` representing the scrollable element (*scroller*) whose scroll position will drive the progress of the timeline.

`axis` Optional

An enumerated value representing the scroll axis that will drive the progress of the timeline. Possible values are:

* `"block"`: The scrollbar on the block axis of the scroll container, which is the axis in the direction perpendicular to the flow of text within a line. For horizontal writing modes, such as standard English, this is the same as `"y"`, while for vertical writing modes, it is the same as `"x"`.
* `"inline"`: The scrollbar on the inline axis of the scroll container, which is the axis in the direction parallel to the flow of text in a line. For horizontal writing modes, this is the same as `"x"`, while for vertical writing modes, this is the same as `"y"`.
* `"y"`: The scrollbar on the vertical axis of the scroll container.
* `"x"`: The scrollbar on the horizontal axis of the scroll container.

If omitted, `axis` defaults to `"block"`.

### Return value

A new `ScrollTimeline` object instance.

Examples
--------

See the main `ScrollTimeline` page for an example.

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

| Specification |
| --- |
| Scroll-driven Animations # dom-scrolltimeline-scrolltimeline |

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

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

See also
--------

* Web Animations API
* CSS scroll-driven animations
* `ScrollTimeline`
* `AnimationTimeline`, `ViewTimeline`


ScrollTimeline: source property - Web APIs

ScrollTimeline: source property
===============================

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

 The **`source`** read-only property of the
 `ScrollTimeline` interface returns a reference to the scrollable element (*scroller*) whose scroll position is driving the progress of the timeline and therefore the animation.

Value
-----

An `Element`.

Examples
--------

See the main `ScrollTimeline` page for an example.

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

| Specification |
| --- |
| Scroll-driven Animations # dom-scrolltimeline-source |

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

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

See also
--------

* Web Animations API
* CSS scroll-driven animations
* `ScrollTimeline`
* `AnimationTimeline`, `ViewTimeline`


WakeLock: request() method - Web APIs

WakeLock: request() method
==========================

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

The **`request()`** method of the `WakeLock` interface returns a `Promise` that fullfills with a `WakeLockSentinel` object if the system screen wake lock is granted.

The screen wake lock prevents device screens from dimming or locking when an application needs to keep running.

Syntax
------

```js
request(type)
```

### Parameters

`type` Optional

A string specifying the screen wake lock type, from among the following enumerated types:

`screen`

 Prevents the screen from turning off.
 Only visible documents can acquire the screen wake lock.

If no `type` parameter is explicitly specified, the `request()` method defaults to using the `screen` type.

### Return value

A `Promise` that resolves with a `WakeLockSentinel` object.

### Exceptions

`NotAllowedError` `DOMException`

Thrown when wake lock is not available, which can happen because:

* Use of this feature is blocked by a Permissions Policy.
* The document is not fully active.
* The document's visibility state is `hidden`.
* The User Agent could not acquire platform's wake lock.
 For example, this might happen if the device is low on battery.

Examples
--------

 The following asynchronous function requests a `WakeLockSentinel` object.
 The `request()` method is wrapped in a `try...catch` statement to handle cases where the browser refuses the request for any reason.

```js
const requestWakeLock = async () => {
  try {
    const wakeLock = await navigator.wakeLock.request("screen");
  } catch (err) {
    // The wake lock request fails - usually system-related, such as low battery.

    console.log(`${err.name}, ${err.message}`);
  }
};

requestWakeLock();
```

 The screen wake lock may be revoked by the device after it has been granted.
 The returned `WakeLockSentinel` can be used to check the status of the lock, and/or to manually cancel a held screen wake lock.

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

| Specification |
| --- |
| Screen Wake Lock API # the-request-method |

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

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

See also
--------

* Stay awake with the Screen Wake Lock API


WebSocket: bufferedAmount property - Web APIs

WebSocket: bufferedAmount property
==================================

 The **`WebSocket.bufferedAmount`** read-only property returns
 the number of bytes of data that have been queued using calls to `send()` but
 not yet transmitted to the network. This value resets to zero once all queued data has
 been sent. This value does not reset to zero when the connection is closed; if you keep
 calling `send()`, this will continue to climb.

Value
-----

An `unsigned long`.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-bufferedamount① |

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

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


WebSocket: extensions property - Web APIs

WebSocket: extensions property
==============================

 The **`WebSocket.extensions`** read-only property returns the
 extensions selected by the server. This is currently only the empty string or a list of
 extensions as negotiated by the connection.

Value
-----

A string.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-extensions① |

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

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


WebSocket: message event - Web APIs

WebSocket: message event
========================

The `message` event is fired when data is received through a `WebSocket`.

Syntax
------

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

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

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

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

A `MessageEvent`. Inherits from `Event`.

Event

MessageEventEvent properties
----------------

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

`data` Read only

The data sent by the message emitter. The type of this property depends on the type of the WebSocket message and the value of `WebSocket.binaryType`.

* If the message type is "text", then this field is a string.
* If the message type is "binary" type, then the type of this property can be inferred from the `binaryType` of this socket:
    + `ArrayBuffer` if `binaryType` is `"arraybuffer"`,
    + `Blob` if `binaryType` is `"blob"`. This does not have an associated media type (`Blob.type` is `""`).

`origin` Read only

A string representing the origin of the message emitter.

Other properties from the `MessageEvent` interface are present, but do not pertain to the WebSocket API and are left at their default values:

* `lastEventId` Read only
* `source` Read only
* `ports` Read only
Examples
--------

```js
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");

// Listen for messages
socket.addEventListener("message", (event) => {
  console.log("Message from server ", event.data);
});
```

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

| Specification |
| --- |
| WebSockets Standard # dom-websocket-onmessage |

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

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

See also
--------

* WebSocket: close event
* WebSocket: error event
* WebSocket: open event
* Writing WebSocket client applications


WebSocket: protocol property - Web APIs

WebSocket: protocol property
============================

 The **`WebSocket.protocol`** read-only property returns the
 name of the sub-protocol the server selected; this will be one of the strings specified
 in the `protocols` parameter when creating the `WebSocket`
 object, or the empty string if no connection is established.

Value
-----

A string.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-protocol① |

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

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


WebSocket: WebSocket() constructor - Web APIs

WebSocket: WebSocket() constructor
==================================

 The **`WebSocket()`** constructor returns a new
 `WebSocket` object.

Syntax
------

```js
new WebSocket(url)
new WebSocket(url, protocols)
```

### Parameters

`url`

 The URL to which to connect; this should be the URL to which the WebSocket server
 will respond.

`protocols` Optional

 Either a single protocol string or an array of protocol strings. These strings are
 used to indicate sub-protocols, so that a single server can implement multiple
 WebSocket sub-protocols (for example, you might want one server to be able to handle
 different types of interactions depending on the specified `protocol`).

If it is omitted, an empty array is used by default, i.e. `[]`.

### Exceptions

`SyntaxError` `DOMException`

Thrown if:

* parsing of `url` fails
* `url` has a scheme other than `ws` or `wss`
* `url` has a fragment
* any of the values in `protocols` occur more than once, or otherwise fail to match the requirements for elements that comprise the value of `Sec-WebSocket-Protocol` fields as defined by the WebSocket Protocol specification

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-websocket① |

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

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

See also
--------

* RFC 6455 (the WebSocket Protocol specification)


WebSocket: close event - Web APIs

WebSocket: close event
======================

The `close` event is fired when a connection with a `WebSocket` is closed.

Syntax
------

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

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

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

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

A `CloseEvent`. Inherits from `Event`.

Event

CloseEventEvent properties
----------------

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

`code` Read only

Returns an `unsigned short` containing the close code sent by the server.

`reason` Read only

Returns a string indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.

`wasClean` Read only

Returns a boolean value that Indicates whether or not the connection was cleanly closed.

Examples
--------

You might want to know when the connection has been closed so that you can update the UI or, perhaps, save data about the closed connection. Given that you have a variable called `exampleSocket` that refers to an opened `WebSocket`, this handler would handle the situation where the socket has been closed.

```js
exampleSocket.addEventListener("close", (event) => {
  console.log("The connection has been closed successfully.");
});
```

You can perform the same actions using the event handler property, like this:

```js
exampleSocket.onclose = (event) => {
  console.log("The connection has been closed successfully.");
};
```

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

| Specification |
| --- |
| WebSockets Standard # dom-websocket-onclose |

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

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

See also
--------

* WebSocket: error event
* WebSocket: message event
* WebSocket: open event
* Writing WebSocket client applications


WebSocket: url property - Web APIs

WebSocket: url property
=======================

 The **`WebSocket.url`** read-only property returns the absolute
 URL of the `WebSocket` as resolved by the constructor.

Value
-----

A string.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-url① |

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

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


WebSocket: close() method - Web APIs

WebSocket: close() method
=========================

 The **`WebSocket.close()`** method closes the
 `WebSocket` connection or connection attempt, if any. If the connection is
 already `CLOSED`, this method does nothing.

**Note:** The process of closing the connection begins with a closing handshake, and the `close()` method does not discard previously-sent messages before starting that closing handshake; even if the user agent is still busy sending those messages, the handshake will only start after the messages are sent.

Syntax
------

```js
close()
close(code)
close(code, reason)
```

### Parameters

`code` Optional

An integer WebSocket connection close code value indicating a reason for closure:

* If unspecified, a close code for the connection is automatically set: to `1000` for a normal closure, or otherwise to another standard value in the range `1001`-`1015` that indicates the actual reason the connection was closed.
* If specified, the value of this `code` parameter overrides the automatic setting of the close code for the connection, and instead sets a custom code.
 The value must be an integer: either `1000`, or else a custom code of your choosing in the range `3000`-`4999`. If you specify a `code` value, you should also specify a `reason` value.

`reason` Optional

A string providing a custom WebSocket connection close reason (a concise human-readable prose explanation for the closure). The value must be no longer than 123 bytes (encoded in UTF-8).

**Note:** Because UTF-8 uses two to four bytes to encode any non-ASCII characters, a 123-character `reason` value containing non-ASCII characters would exceed the 123-byte limit.

If you specify a `reason` value, you should also specify a `code` value.

### Return value

None (`undefined`).

### Exceptions

`InvalidAccessError` `DOMException`

Thrown if `code` is neither an integer equal to `1000` nor an integer in the range `3000` – `4999`.

`SyntaxError` `DOMException`

Thrown if the UTF-8-encoded `reason` value is longer than 123 bytes.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-close① |

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

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

See also
--------

* RFC 6455 (the WebSocket Protocol specification)


WebSocket: error event - Web APIs

WebSocket: error event
======================

The `error` event is fired when a connection with a `WebSocket` has been closed due to an error (some data couldn't be sent for example).

Syntax
------

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

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

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

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

A generic `Event`.

Examples
--------

```js
// Create WebSocket connection
const socket = new WebSocket("ws://localhost:8080");

// Listen for possible errors
socket.addEventListener("error", (event) => {
  console.log("WebSocket error: ", event);
});
```

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

| Specification |
| --- |
| WebSockets Standard # dom-websocket-onerror |

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

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

See also
--------

* WebSocket: close event
* WebSocket: message event
* WebSocket: open event
* Writing WebSocket client applications


WebSocket: send() method - Web APIs

WebSocket: send() method
========================

 The **`WebSocket.send()`** method enqueues the specified data
 to be transmitted to the server over the WebSocket connection, increasing the value of
 `bufferedAmount` by the number of bytes needed to contain the data. If the
 data can't be sent (for example, because it needs to be buffered but the buffer is
 full), the socket is closed automatically.
 The browser will throw an exception if you call `send()` when the connection is in the `CONNECTING` state. If you call `send()` when the connection is in the `CLOSING` or `CLOSED` states, the browser will silently discard the data.

Syntax
------

```js
send(data)
```

### Parameters

`data`

The data to send to the server. It may be one of the following types:

`string`

 A text string. The string is added to the buffer in UTF-8 format, and the value
 of `bufferedAmount` is increased by the number of bytes required to
 represent the UTF-8 string.

`ArrayBuffer`

 You can send the underlying binary data used by a typed array object; its binary
 data contents are queued in the buffer, increasing the value of
 `bufferedAmount` by the requisite number of bytes.

`Blob`

 Specifying a `Blob` enqueues the blob's raw data to be transmitted in
 a binary frame (the `Blob.type` is ignored).
 The value of `bufferedAmount` is increased by the byte size of that raw data.

`TypedArray` or a `DataView`

 You can send any JavaScript typed array object as a binary frame;
 its binary data contents are queued in the buffer,
 increasing the value of `bufferedAmount` by the requisite number of bytes.

### Return value

None (`undefined`).

### Exceptions

`InvalidStateError` `DOMException`

Thrown if `WebSocket.readyState` is `CONNECTING`.

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-send① |

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

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


WebSocket: readyState property - Web APIs

WebSocket: readyState property
==============================

 The **`WebSocket.readyState`** read-only property returns the
 current state of the `WebSocket` connection.

Value
-----

One of the following `unsigned short` values:

| Value | State | Description |
| --- | --- | --- |
| `0` | `CONNECTING` | Socket has been created. The connection is not yet open. |
| `1` | `OPEN` | The connection is open and ready to communicate. |
| `2` | `CLOSING` | The connection is in the process of closing. |
| `3` | `CLOSED` | The connection is closed or couldn't be opened. |

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-readystate① |

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

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


WebSocket: binaryType property - Web APIs

WebSocket: binaryType property
==============================

 The **`WebSocket.binaryType`** property controls the type of
 binary data being received over the WebSocket connection.

Value
-----

A string:

`"blob"`

Use `Blob` objects for binary data. This is the default value.

`"arraybuffer"`

Use `ArrayBuffer` objects for binary data.

Examples
--------

```js
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");

// Change binary type from "blob" to "arraybuffer"
socket.binaryType = "arraybuffer";

// Listen for messages
socket.addEventListener("message", (event) => {
  if (event.data instanceof ArrayBuffer) {
    // binary frame
    const view = new DataView(event.data);
    console.log(view.getInt32(0));
  } else {
    // text frame
    console.log(event.data);
  }
});
```

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

| Specification |
| --- |
| WebSockets Standard # ref-for-dom-websocket-binarytype① |

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

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


WebSocket: open event - Web APIs

WebSocket: open event
=====================

The `open` event is fired when a connection with a `WebSocket` is opened.

Syntax
------

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

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

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

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

A generic `Event`.

Examples
--------

```js
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");

// Connection opened
socket.addEventListener("open", (event) => {
  socket.send("Hello Server!");
});
```

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

| Specification |
| --- |
| WebSockets Standard # dom-websocket-onopen |

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

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

See also
--------

* WebSocket: close event
* WebSocket: error event
* WebSocket: message event
* Writing WebSocket client applications


RTCRtpStreamStats: trackId property - Web APIs

RTCRtpStreamStats: trackId property
===================================

 The `RTCRtpStreamStats` dictionary's
 **`trackId`** property is a string which uniquely identifies
 the `RTCMediaStreamTrackStats` object which contains the track statistics
 for the `MediaStreamTrack` for which statistics are provided in this
 object.

Value
-----

 A string which uniquely identifies the
 `RTCMediaStreamTrackStats` object that provides statistics for the track
 for which statistics are being collected by this `RTCStatsReport`.

**Note:** This value is *not* the same as the value of
 `MediaStreamTrack.id`.

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.trackId`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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


RTCRtpStreamStats: ssrc property - Web APIs

RTCRtpStreamStats: ssrc property
================================

 The `RTCRtpStreamStats` dictionary's
 **`ssrc`** property provides the Synchronization Source
 (SSRC), an integer which uniquely identifies the source of the RTP
 packets whose statistics are covered by the `RTCStatsReport` that
 includes this `RTCRtpStreamStats` dictionary.

Value
-----

 The Synchronization Source (SSRC) is a 32-bit integer uniquely identifying the source
 of the RTP packets whose statistics are covered by the `RTCStatsReport`
 object of which this `RTCRtpStreamStats` object is a component.

 The manner in which these values are generated is not mandated by the specification,
 although it does make recommendations. You should not make any assumptions based on the
 value of `ssrc` other than that any two objects with the same
 `ssrc` value refer to the same source. See RFC 3550, section 8 for
 additional information about `ssrc`.

**Note:** The specification includes an example that generates values
 for `ssrc` using MD5. While not part of the standard, exactly, it is a good
 mechanism that may be used by some browsers; others may use other methods, such as
 random number generators. *Do not* rely upon these values meaning anything
 other than "these objects are associated with the same source."

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.ssrc`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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


RTCRtpStreamStats: kind property - Web APIs

RTCRtpStreamStats: kind property
================================

 The **`kind`** property of the
 `RTCRtpStreamStats` dictionary is a string indicating whether the
 described RTP stream contains audio or video media.

 Its value
 is always either `"audio"` or `"video"`.

 This property was previously called `mediaType`. The name was changed in the
 specification in February, 2018. See Browser compatibility below to
 determine how this affects the browsers you're targeting.

Value
-----

 A string whose value is `"audio"` if the track whose
 statistics are given by the `RTCRtpStreamStats` object contains audio, or
 `"video"` if the track contains video media.

 This string will always be the same as the one provided by the associated
 `MediaStreamTrack` object's `kind`
 property. It will also match the statistics object's `RTCCodecStats.codec`
 property's media type.

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.kind`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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


RTCRtpStreamStats: nackCount property - Web APIs

RTCRtpStreamStats: nackCount property
=====================================

 The **`nackCount`** property of the
 `RTCRtpStreamStats` dictionary is a numeric value indicating the number
 of times the receiver sent a **NACK packet** to the sender.

 A NACK
 (Negative ACKnowledgement, also called "Generic NACK") packet tells the sender that one
 or more of the RTP packets it sent were lost in transport.

Value
-----

 An integer value indicating how many times the receiver sent a NACK packet to the
 sender after detecting that one or more packets were lost during transport.

**Note:** This value is only available on the receiver.

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.nackCount`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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


RTCRtpStreamStats: qpSum property - Web APIs

RTCRtpStreamStats: qpSum property
=================================

 The **`qpSum`** property of the
 `RTCRtpStreamStats` dictionary is a value generated by adding the
 **Quantization Parameter** (**QP**) values for every frame
 sent or received to date on the video track corresponding to this
 `RTCRtpStreamStats` object.

 In general, the higher this number is,
 the more heavily compressed the video data is.

Value
-----

 An unsigned 64-bit integer value which indicates the sum of the quantization parameter
 (QP) value for every frame sent or received so far on the track described by the
 `RTCRtpStreamStats` object. Since the value of QP is typically larger to
 indicate higher compression factors, the larger this sum is, the more heavily compressed
 the stream generally has been.

**Note:** This value is only available for video media.

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

Quantization is the process of applying lossy compression
 to a range of values, resulting in a single **quantum value**. This value
 takes the place of the range of values, thereby reducing the number of different values
 that appear in the overall data set, making the data more compressible. The quantization
 process and the amount of compression can be controlled using one or more parameters.

 It's important to keep in mind that the value of QP can change periodically—even every
 frame—so it's difficult to know for certain how substantial the compression is. The best
 you can do is make an estimate. You can, for example, use the value of
 `RTCReceivedRtpStreamStats.framesDecoded` if receiving the media or
 `RTCSentRtpStreamStats.framesEncoded` if sending it to get the number of
 frames handled so far, and compute an average from there. See Calculating average quantization below for a function that does this.

 Also, the exact meaning of the QP value depends on the codec being
 used. For example, for the VP8 codec, the QP value can be anywhere from 1 to 127 and is
 found in the frame header element `"y_ac_qi"`, whose value is defined in
 RFC 6386, section 19.2. H.264 uses a QP which ranges from 0 to 51; in this case, it's an
 index used to derive a scaling matrix used during the quantization process.
 Additionally, QP is not likely to be the only parameter the codec uses to adjust the
 compression. See the individual codec specifications for details.

Examples
--------

### Calculating average quantization

 The `calculateAverageQP()` function shown below computes the average QP for
 the given `RTCRtpStreamStats` object, returning 0 if the object doesn't
 describe an RTP stream.

```js
function calculateAverageQP(stats) {
  let frameCount = 0;

  switch (stats.type) {
    case "inbound-rtp":
    case "remote-inbound-rtp":
      frameCount = stats.framesDecoded;
      break;
    case "outbound-rtp":
    case "remote-outbound-rtp":
      frameCount = stats.framesEncoded;
      break;
    default:
      return 0;
  }

  return status.qpSum / frameCount;
}
```

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.qpSum`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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


RTCRtpStreamStats: codecId property - Web APIs

RTCRtpStreamStats: codecId property
===================================

 The `RTCRtpStreamStats` dictionary's
 **`codecId`** property is a string which uniquely identifies
 the object that was inspected to produce the data in the `RTCCodecStats`
 for the RTP stream.

Value
-----

 A string which uniquely identifies the object from which the contents
 of the stream's `RTCCodecStats` are derived.

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

#### No specification found

No specification data found for `api.RTCRtpStreamStats.codecId`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

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

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