CSSSkewY: ay property - Web APIs

CSSSkewY: ay property
=====================

 The **`ay`** property of the
 `CSSSkewY` interface gets and sets the angle used to distort the element
 along the y-axis (or ordinate).

Value
-----

A `CSSNumericValue`.

Examples
--------

To do

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

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-cssskewy-ay |

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

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


Metadata: size property - Web APIs

Metadata: size property
=======================

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

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

 The read-only **`size`** property of
 the `Metadata` interface specifies the size, in bytes, of the referenced
 file or other file system object on disk.

Value
-----

A number indicating the size of the file in bytes.

Examples
--------

 This example checks the size of a log file and removes it if it's larger than a
 megabyte.

```js
workingDirectory.getFile(
  "log/important.log",
  {},
  (fileEntry) => {
    fileEntry.getMetadata((metadata) => {
      if (metadata.size > 1048576) {
        fileEntry.remove(() => {
          /\* log file removed; do something clever here \*/
        });
      }
    });
  },
  handleError,
);
```

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

This feature has been removed from all specification and is not in the process of being standardized.

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

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

See also
--------

* File and Directory Entries API
* Introduction to the File and Directory Entries API
* `Metadata`
* `FileSystemEntry.getMetadata()`
* `FileSystemFileEntry`


Metadata: modificationTime property - Web APIs

Metadata: modificationTime property
===================================

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

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

 The read-only **`modificationTime`**
 property of the `Metadata` interface is a `Date` object which
 specifies the date and time the file system entry (or the data referenced by the
 entry) was last modified. A file system entry is considered to have been
 modified if the metadata or the contents of the referenced file (or directory, or
 whatever other kind of file system entry might exist on the platform in use) has
 changed.

Value
-----

A `Date` timestamp indicating when the file system entry was last changed.

Examples
--------

 This example tries to get a particular working file at `tmp/workfile.json`.
 Once that file has been found, its metadata is obtained and the file's modification
 timestamp year is compared to the current year. If it was last modified in a year at
 least five prior to the current year, the file is removed and a new one is created.

```js
workingDirectory.getFile(
  "tmp/workfile.json",
  { create: true },
  (fileEntry) => {
    fileEntry.getMetadata((metadata) => {
      if (
        new Date().getFullYear() - metadata.modificationTime.getFullYear() >=
        5
      ) {
        fileEntry.remove(() => {
          workingDirectory.getFile(
            "tmp/workfile.json",
            { create: true },
            (newEntry) => {
              fileEntry = newEntry;
            },
          );
        });
      }
    });
  },
  handleError,
);
```

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

This feature has been removed from all specification and is not in the process of being standardized.

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

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

See also
--------

* File and Directory Entries API
* Introduction to the File and Directory Entries API
* `Metadata`
* `FileSystemEntry.getMetadata()`
* `FileSystemFileEntry`


CustomElementRegistry: whenDefined() method - Web APIs

CustomElementRegistry: whenDefined() method
===========================================

 The **`whenDefined()`** method of the
 `CustomElementRegistry` interface returns a `Promise` that
 resolves when the named element is defined.

Syntax
------

```js
whenDefined(name)
```

### Parameters

`name`

The name of the custom element.

### Return value

A `Promise` that fulfills with the custom element's constructor when a custom element becomes defined with the given name. If a custom element has already been defined with the name, the promise will immediately fulfill.

The promise is rejected with a `SyntaxError` `DOMException` if the name is not a valid custom element name.

Examples
--------

 This example uses `whenDefined()` to detect when the custom elements that
 make up a menu are defined. The menu displays placeholder content until the actual menu
 content is ready to display.

```html
<nav id="menu-container">
  <div class="menu-placeholder">Loading…</div>
  <nav-menu>
    <menu-item>Item 1</menu-item>
    <menu-item>Item 2</menu-item>
    …
    <menu-item>Item N</menu-item>
  </nav-menu>
</nav>
```

```js
const container = document.getElementById("menu-container");
const placeholder = container.querySelector(".menu-placeholder");
// Fetch all the children of menu that are not yet defined.
const undefinedElements = container.querySelectorAll(":not(:defined)");

async function removePlaceholder() {
  const promises = [...undefinedElements].map((button) =>
    customElements.whenDefined(button.localName),
  );

  // Wait for all the children to be upgraded
  await Promise.all(promises);
  // then remove the placeholder
  container.removeChild(placeholder);
}

removePlaceholder();
```

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

| Specification |
| --- |
| HTML Standard # dom-customelementregistry-whendefined-dev |

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

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


CustomElementRegistry: get() method - Web APIs

CustomElementRegistry: get() method
===================================

 The **`get()`** method of the
 `CustomElementRegistry` interface returns the constructor for a
 previously-defined custom element.

Syntax
------

```js
get(name)
```

### Parameters

`name`

The name of the custom element.

### Return value

The constructor for the named custom element, or `undefined` if there is no custom element defined with the name.

Examples
--------

```js
customElements.define(
  "my-paragraph",
  class extends HTMLElement {
    constructor() {
      let templateContent = document.getElementById("my-paragraph").content;
      super() // returns element this scope
        .attachShadow({ mode: "open" }) // sets AND returns this.shadowRoot
        .append(templateContent.cloneNode(true));
    }
  },
);

// Return a reference to the my-paragraph constructor
let ctor = customElements.get("my-paragraph");
```

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

| Specification |
| --- |
| HTML Standard # dom-customelementregistry-get-dev |

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

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


CustomElementRegistry: upgrade() method - Web APIs

CustomElementRegistry: upgrade() method
=======================================

 The **`upgrade()`** method of the
 `CustomElementRegistry` interface upgrades all shadow-containing custom
 elements in a `Node` subtree, even before they are connected to the main
 document.

Syntax
------

```js
upgrade(root)
```

### Parameters

`root`

 A `Node` instance with shadow-containing descendant elements to upgrade. If there are no descendant elements that can be upgraded, no error is
 thrown.

### Return value

None (`undefined`).

Examples
--------

Taken from the HTML spec:

```js
const el = document.createElement("spider-man");

class SpiderMan extends HTMLElement {}
customElements.define("spider-man", SpiderMan);

console.assert(!(el instanceof SpiderMan)); // not yet upgraded

customElements.upgrade(el);
console.assert(el instanceof SpiderMan); // upgraded!
```

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

| Specification |
| --- |
| HTML Standard # dom-customelementregistry-upgrade-dev |

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

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


CustomElementRegistry: getName() method - Web APIs

CustomElementRegistry: getName() method
=======================================

 The **`getName()`** method of the
 `CustomElementRegistry` interface returns the name for a
 previously-defined custom element.

Syntax
------

```js
getName(constructor)
```

### Parameters

`constructor`

Constructor for the custom element.

### Return value

The name for the previously defined custom element, or `null` if there is no custom element defined with the constructor.

Examples
--------

```js
class MyParagraph extends HTMLElement {
  constructor() {
    let templateContent = document.getElementById("my-paragraph").content;
    super() // returns element this scope
      .attachShadow({ mode: "open" }) // sets AND returns this.shadowRoot
      .append(templateContent.cloneNode(true));
  }
}

customElements.define("my-paragraph", MyParagraph);

// Return a reference to the my-paragraph constructor
customElements.getName(MyParagraph) === "my-paragraph";
```

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

| Specification |
| --- |
| HTML Standard # dom-customelementregistry-getname |

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

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


CustomElementRegistry: define() method - Web APIs

CustomElementRegistry: define() 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 **`define()`** method of the `CustomElementRegistry` interface adds a definition for a custom element to the custom element registry, mapping its name to the constructor which will be used to create it.

Syntax
------

```js
define(name, constructor)
define(name, constructor, options)
```

### Parameters

`name`

Name for the new custom element. Must be a valid custom element name.

`constructor`

Constructor for the new custom element.

`options` Optional

Object that controls how the element is defined. One option is currently supported:

`extends`

 String specifying the name of a built-in element to
 extend. Used to create a customized built-in element.

### Return value

None (`undefined`).

### Exceptions

`NotSupportedError` `DOMException`

Thrown if:

* The `CustomElementRegistry` already contains an entry with the same name or the same constructor (or is otherwise already defined).
* The `extends` option is specified and it is a valid custom element name
* The `extends` option is specified but the element it is trying to extend is an unknown element.

`SyntaxError` `DOMException`

Thrown if the provided name is not a valid custom element name.

`TypeError`

Thrown if the referenced constructor is not a constructor.

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

The `define()` method adds a definition for a custom element to the custom element registry, mapping its name to the constructor which will be used to create it.

There are two types of custom element you can create:

* *Autonomous custom elements* are standalone elements, that don't inherit from built-in HTML elements.
* *Customized built-in elements* are elements that inherit from, and extend, built-in HTML elements.

To define an autonomous custom element, you should omit the `options` parameter.

To define a customized built-in element, you must pass the `options` parameter with its `extends` property set to the name of the built-in element that you are extending, and this must correspond to the interface that your custom element class definition inherits from. For example, to customize the `<p>` element, you must pass `{extends: "p"}` to `define()`, and the class definition for your element must inherit from `HTMLParagraphElement`.

### Valid custom element names

Custom element names must:

* start with an ASCII lowercase letter (a-z)
* contain a hyphen
* not contain any ASCII uppercase letters
* not contain certain other characters, as documented in the valid custom element names section of the Web Components specification
* not be any of:
    + "annotation-xml"
    + "color-profile"
    + "font-face"
    + "font-face-src"
    + "font-face-uri"
    + "font-face-format"
    + "font-face-name"
    + "missing-glyph"
Examples
--------

### Defining an autonomous custom element

The following class implements a minimal autonomous custom element:

```js
class MyAutonomousElement extends HTMLElement {
  constructor() {
    super();
  }
}
```

This element doesn't do anything: a real autonomous element would implement its functionality in its constructor and in the lifecycle callbacks provided by the standard. See Implementing a custom element in our guide to working with custom elements.

However, the above class definition satisfies the requirements of the `define()` method, so we can define it with the following code:

```js
customElements.define("my-autonomous-element", MyAutonomousElement);
```

We could then use it in an HTML page like this:

```html
<my-autonomous-element>Element contents</my-autonomous-element>
```

### Defining a customized built-in element

The following class implements a customized built-in element:

```js
class MyCustomizedBuiltInElement extends HTMLParagraphElement {
  constructor() {
    super();
  }
}
```

This element extends the built-in `<p>` element.

In this minimal example the element doesn't implement any customization, so it will behave just like a normal `<p>` element. However, it does satisfy the requirements of `define()`, so we can define it like this:

```js
customElements.define(
  "my-customized-built-in-element",
  MyCustomizedBuiltInElement,
  {
    extends: "p",
  },
);
```

We could then use it in an HTML page like this:

```html
<p is="my-customized-built-in-element"></p>
```

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

| Specification |
| --- |
| HTML Standard # dom-customelementregistry-define-dev |

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

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

See also
--------

* Using custom elements


Non-cryptographic uses of SubtleCrypto - Web APIs

Non-cryptographic uses of SubtleCrypto
======================================

This article will focus on uses of the `digest` method of the SubtleCrypto interface. A lot of other methods within the Web Crypto API have very specific cryptographic use cases, creating hashes of content (which is what the digest method does) has lots of very useful purposes.

This article does not discuss the cryptographic uses of the SubtleCrypto interface. An important thing to take away from this article is **don't use this API** for production cryptographic purposes because it is powerful and low level. To use it correctly you will need to take many context specific steps to accomplish cryptographic tasks correctly. If any of those steps are taken incorrectly at best your code won't run, at worse it *will* run and you will unknowingly be putting your users at risk with an insecure product.

You may not even need to use the Web Crypto API at all. Many of the things you would want to use cryptography for are already solved and part of the Web platform. For example, if you are worried about man-in-the-middle attacks, such as Wi-Fi hotspots reading the information between the client and the server, this is solved by ensuring correct use of HTTPS. Do you want to securely send information between users? Then you can set up a data connection between users using WebRTC Data Channels which is encrypted as part of the standard.

The SubtleCrypto interface provides low level primitives for working with cryptography, but implementing a system using these tools is a complicated task. Mistakes are hard to notice and the results can mean your user's data is not as secure as you think it is. Which could have catastrophic results if your users are sharing sensitive or valuable data.

If in doubt don't try doing it yourself, hire someone with experience and ensure your software is audited by a security expert.

Hashing a file
--------------

This is the simplest useful thing you can do with the Web Crypto API. It doesn't involve generating keys or certificates and has one single step.

Hashing is a technique where you convert a large string of bytes into a smaller string, where small changes to the long string result in large changes in the smaller string. This technique is useful for identifying two identical files without checking every byte of both files. This is very useful as you have a simple string to compare. To be clear hashing is a **one way** operation. You cannot generate the original string of bytes from the hash.

If two generated hashes are the same, but the files that used to generate them are different, that is known as a *hash collision* which is an extremely improbable thing to occur by accident and, for a secure hash function like SHA256, almost impossible to manufacture. So if the two strings are the same you can be reasonably sure the two original files are identical.

As of publication, SHA256 is the usual choice for hashing files but there are higher order hashing functions available in the SubtleCrypto interface. The most common representation of a SHA256 hash is a string of 64 hexadecimal digits. Hexadecimal means it only uses the characters 0-9 and a-f, representing 4 bits of information. So in short a SHA256 hash turns any length of data into an almost unique 256 bits of data.

This technique is often used by sites that let you download executables, to ensure that the downloaded file matches the one the author intended. This ensures that your users are not installing malware. The most common way to do this is:

1. Note down the file's name and the SHA256 checksum provided by the website.
2. Download the executable.
3. Run `sha256sum /path/to/the/file` in the terminal to generate your own code. If you are using a Mac you may have to install it separately.
4. Compare the two strings - they should match unless the file has been compromised.

![Examples of SHA256 from the download for the software "Blender". These look like 64 hexadecimal digits followed by a file name like "blender.zip"](/en-US/docs/Web/API/Web_Crypto_API/Non-cryptographic_uses_of_subtle_crypto/blender-sha256-example.png)

The `digest()` method of SubtleCrypto is useful for this. To generate a checksum of a file you can do it like so:

First we add some HTML elements for loading some files and displaying the SHA-256 output:

```html
<h3>Demonstration of hashing a file with SHA256</h3>

<label
 >Choose file(s) to hash <input type="file" id="file" name="file" multiple
/></label>
<output style="display:block;font-family:monospace;"></output>
```

Next we use the SubtleCrypto interface to process them. This works by:

* Reading the files to an `ArrayBuffer` using the `File` object's `arrayBuffer()` method.
* Use `crypto.subtle.digest('SHA-256', arrayBuffer)` to digest the ArrayBuffer
* Convert the resulting hash (another ArrayBuffer) into a string so it can be displayed

```js
const output = document.querySelector("output");
const file = document.getElementById("file");

// Run the hashing function when the user selects one or more file
file.addEventListener("change", hashTheseFiles);

// The digest function is asynchronous, it returns a promise
// We use the async/await syntax to simplify the code.
async function fileHash(file) {
  const arrayBuffer = await file.arrayBuffer();

  // Use the subtle crypto API to perform a SHA256 Sum of the file's
  // Array Buffer. The resulting hash is stored in an array buffer
  const hashAsArrayBuffer = await crypto.subtle.digest("SHA-256", arrayBuffer);

  // To display it as a string we will get the hexadecimal value of
  // each byte of the array buffer. This gets us an array where each byte
  // of the array buffer becomes one item in the array
  const uint8ViewOfHash = new Uint8Array(hashAsArrayBuffer);
  // We then convert it to a regular array so we can convert each item
  // to hexadecimal strings, where characters of 0-9 or a-f represent
  // a number between 0 and 15, containing 4 bits of information,
  // so 2 of them is 8 bits (1 byte).
  const hashAsString = Array.from(uint8ViewOfHash)
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
  return hashAsString;
}

async function hashTheseFiles(e) {
  let outHTML = "";
  // iterate over each file in file select input
  for (const file of this.files) {
    // calculate its hash and list it in the output element.
    outHTML += `${file.name} ${await fileHash(file)}`;
  }
  output.innerHTML = outHTML;
}
```

### Where would you use this?

At this point you may be thinking to yourself "*I can use this on my own website, so when users go to download a file we can ensure the hashes match to reassure the user their download is secure*". Unfortunately this has two issues that immediate spring to mind:

* Executable downloads should **always** be done over HTTPS. This prevents intermediate parties from performing attacks like this so it would be redundant.
* If the attacker is able to replace the download file on the original server, then they can also simply replace the code which invokes the SubtleCrypto interface to bypass it and just state that everything is fine. Probably something sneaky like replacing strict equality, which can be a pain to spot in your own code:

```diff
--- if (checksum === correctCheckSum) return true;
+++ if (checksum = correctCheckSum) return true;
```

One place it may be worthwhile, is if you want to test a file from a third party download source, which you do not control. This would be the case as long as the download location has CORS headers enabled to let you scan the file before you make it available to your users. Unfortunately not many servers have CORS turned on by default.

What is "Salting the Hash"?
---------------------------

A phrase you may have heard before is *"Salting the hash"*. It's not immediately relevant to our topics at hand, but it is good to know about.

**Note:** this section is talking about password security and the hash functions provided by SubtleCrypto are not suitable for this use case. For these purposes you need expensive slow hash functions like `scrypt` and `bcrypt`. SHA is designed to be pretty fast and efficient, which makes it unsuitable for password hashing. This section is purely for your interest — do not use the Web Crypto API to hash passwords on the client.

A popular use case for hashing is passwords, you never ever want to store a users password in plain text, its simply a terrible idea. Instead you store a hash of the users password, so the original password cannot be recovered should a hacker obtain your username and password database. The eagle eyed among may notice you can still work out the original passwords by comparing the hashes from lists of known passwords against the obtained password hash list. Concatenating a string to the passwords changes the hash so it no longer matches. This is known as **salting**. Another tricky problem is if you use the same salt for each password, then passwords with matching hashes will also be the same original password. Thus if you know one then you know all matching passwords.

To solve this issue, you perform what is known as *salting the hash*. For each password, you generate a salt (a random string of characters) and concatenate that with the password string. You then store the hash and the salt in the same database so you can check a match when the user tries to log in later. This means that if two users use the same password the hashes will be different. Hence the reason why you need an expensive cryptographic function, so it makes it too time consuming to use lists of common passwords to find out what the original passwords were.

Hash Tables with SHA
--------------------

You can use SHA1 to quickly generate non-cryptographically secure hashes. These are incredibly useful for turning some arbitrary data into a key you can look up later.

For example, if you want to have a database which includes a large blob of data as one of the fields in a row. This decreases the efficiency of your database because one of the fields has to be either variable length, or large enough to store the largest possible blob. An alternative solution is to generate a hash of the blob and store it in a separate look up table using the hash as the index. You can then store just the hash in your original database which is a nice fixed length.

The possible variations for a SHA1 hash are incredibly numerous. So much so that accidentally producing two blobs with the same SHA1 hash is nearly-impossible. It *is* possible to intentionally produce two files with the same SHA1 hash, because SHA1 is not cryptographically secure. So a malicious user could in theory generate a blob of data that replaces the original in the database, which goes undetected because the hash is the same. This is an attack vector worth being aware of.

How git stores files
--------------------

Git uses SHA1 hashes and is a great example here, it uses hashes in two interesting ways. When files are stored in git, they are referenced by their SHA1 hash. This makes it quick for git to find the data and restore files.

It doesn't just use the file contents for the hash however, it also prepends it with the UTF8 string `"blob "`, followed by the file size in bytes written in decimal, followed by the null character (which in JavaScript can be written `"\0"`). You can use the TextEncoder interface of the Encoding API to encode the UTF8 text, since strings in JavaScript are UTF16.

The code below, like our SHA256 example, can be used to generate these hashes from files. The HTML to upload files remains the same, but we do some additional work to prepend the size information in the same way git does.

```html
<h3>Demonstration of how git uses SHA1 for files</h3>

<label
 >Choose file(s) to hash <input type="file" id="file" name="file" multiple
/></label>

<output style="display:block;font-family:monospace;"></output>
```

```js
const output = document.querySelector("output");
const file = document.getElementById("file");
file.addEventListener("change", hashTheseFiles);

async function fileHash(file) {
  const arrayBuffer = await file.arrayBuffer();

  // Git prepends the null terminated text 'blob 1234' where 1234
  // represents the file size before hashing so we are going to reproduce that

  // first we work out the Byte length of the file
  const uint8View = new Uint8Array(arrayBuffer);
  const length = uint8View.length;

  // Git in the terminal uses UTF8 for its strings; the Web uses UTF16.
  // We need to use an encoder because different binary representations
  // of the letters in our message will result in different hashes
  const encoder = new TextEncoder();
  // Null-terminated means the string ends in the null character which
  // in JavaScript is '\0'
  const view = encoder.encode(`blob ${length}\0`);

  // We then combine the 2 Array Buffers together into a new Array Buffer.
  const newBlob = new Blob([view.buffer, arrayBuffer], {
    type: "text/plain",
  });
  const arrayBufferToHash = await newBlob.arrayBuffer();

  // Finally we perform the hash this time as SHA1 which is what Git uses.
  // Then we return it as a string to be displayed.
  return hashToString(await crypto.subtle.digest("SHA-1", arrayBufferToHash));
}

function hashToString(arrayBuffer) {
  const uint8View = new Uint8Array(arrayBuffer);
  return Array.from(uint8View)
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

// like before we iterate over the files
async function hashTheseFiles(e) {
  let outHTML = "";
  for (const file of this.files) {
    outHTML += `${file.name} ${await fileHash(file)}`;
  }
  output.innerHTML = outHTML;
}
```

Notice how it uses the Encoding API to produce the header, which is concatenated with the original ArrayBuffer to produce the string to be hashed.

How git generates commit hashes
-------------------------------

Interestingly git also generates commit hashes in a similar way based upon multiple pieces of information. These can include the previous commit hash and the commit message, which come together to make a new hash. This can be used to reference commits which are based on several unique identifiers.

The terminal command is: `(printf "commit %s\0" $(git --no-replace-objects cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum`

Source: How is git commit sha1 formed

Essentially it's the UTF8 string (null character written as `\0`):
```

commit [size in bytes as decimal of this info]\0tree [tree hash]
parent [parent commit hash]
author [author info] [timestamp]
committer [committer info] [timestamp]

commit message
```

This is great because none of the individual fields are guaranteed to be unique, but when combined together give a unique pointer to a single commit. However, the whole string is too long and unwieldy to use. So by hashing it you get a new unique string which is short enough to share conveniently from multiple fields.

This is why the hash changes if you have ever amended your commit, even if you don't make any changes to the message. The timestamp of the commit has changed, which even by a single character, is enough to totally change the new hash.

The take away from this is that when you want to add a key to some data, but any single piece of information isn't unique enough, then concatenating multiple strings together and hashing them is a great way to generate a useful key.

Hopefully these examples have encourage you to take a look at this new powerful API. Remember don't try recreating cryptography things yourself. Its enough to know the tools are there and some of them like the `crypto.digest()` function are useful tools for your day to day development.


AnimationEffect: getTiming() method - Web APIs

AnimationEffect: getTiming() method
===================================

Baseline 2022
-------------

Newly availableSince September 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
The `AnimationEffect.getTiming()` method of the `AnimationEffect` interface returns an object containing the timing properties for the Animation Effect.

**Note:** Several of the timing properties returned by `getTiming()` may take on the placeholder value `"auto"`. To obtain resolved values for use in timing computations, instead use `AnimationEffect.getComputedTiming()`.

In the future, `"auto"` or similar values might be added to the types of more timing properties, and new types of `AnimationEffect` might resolve `"auto"` to different values.

Syntax
------

```js
getTiming()
```

### Parameters

None.

### Return value

An object containing the following properties:

`delay`

The `number` of milliseconds of delay before the start of the effect.

(See also `animation-delay`.)

`direction`

`"normal"`, `"reverse"`, `"alternate"`, or `"alternate-reverse"`.

 Indicates whether the effect runs forwards (`"normal"`), backwards (`"reverse"`), switches direction
 after each iteration (`"alternate"`), or runs backwards and switches direction after each iteration
 (`"alternate-reverse"`).

(See also `animation-direction`.)

`duration`

A `number` of milliseconds or the `string` `"auto"`.

Indicates the time one iteration of the animation takes to complete.

The meaning of `"auto"` may differ depending on the type of effect; for `KeyframeEffect`, `"auto"` is the same as `0`.

(See also `animation-duration`.)

`easing`

A `string` representing an `<easing-function>` describing the rate of change of the effect over time.

(See also `animation-timing-function`.)

`endDelay`

The `number` of milliseconds of delay after the end of the effect.

This is primarily of use when sequencing animations based on the end time of another animation.

`fill`

`"none"`, `"forwards"`, `"backwards"`, "`both`", or `"auto"`.

 Indicates whether the effect is reflected by its target(s) prior to playing
 (`"backwards"`), retained after the effect has completed (`"forwards"`), `"both"`, or
 neither (`"none"`).

 The meaning of `"auto"` may differ depending on the type of effect; for
 `KeyframeEffect`, `"auto"` is the same as `"none"`.

(See also `animation-fill-mode`.)

`iterations`

 The `number` of times the effect will repeat. A value of `Infinity` indicates that
 the effect repeats indefinitely.

(See also `animation-iteration-count`.)

`iterationStart`

 A `number` indicating at what point in the iteration the effect starts. For example, an effect with
 an `iterationStart` of 0.5 and 2 `iterations` would start halfway through its first iteration
 and end halfway through a third iteration.

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

| Specification |
| --- |
| Web Animations # dom-animationeffect-gettiming |

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

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

See also
--------

* Web Animations API
* `AnimationEffect`


AnimationEffect: updateTiming() method - Web APIs

AnimationEffect: updateTiming() method
======================================

Baseline 2022
-------------

Newly availableSince September 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
The `updateTiming()` method of the `AnimationEffect` interface updates the specified timing properties for an animation effect.

Syntax
------

```js
updateTiming(timing)
```

### Parameters

`timing` Optional

An object containing zero or more of the properties from the return value of `AnimationEffect.getTiming()`, representing the timing properties to update.

### Return value

None (`undefined`).

### Exceptions

`TypeError`

Thrown if invalid values are provided for any of the timing properties.

### Examples

#### Side effects

`updateTiming()` may cause any associated `Animation` to start or stop playing, if for example the effect of a running animation is shortened such that its end time is before `Animation.currentTime` or the effect of a finished animation is lengthened such that its end time is after `Animation.currentTime`.

```js
const animation = document.body.animate([], { duration: 1000 });
animation.finish();
console.log(animation.playState); // finished
animation.effect.updateTiming({ duration: 2000 });
console.log(animation.playState); // running
```

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

| Specification |
| --- |
| Web Animations # dom-animationeffect-updatetiming |

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

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

See also
--------

* Web Animations API
* `AnimationEffect`
* `Animation`
* `AnimationEffect.getTiming()`
* `AnimationEffect.getComputedTiming()`


AnimationEffect: getComputedTiming() method - Web APIs

AnimationEffect: getComputedTiming() method
===========================================

Baseline 2022
-------------

Newly availableSince September 2022, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

* Learn more
* See full compatibility
* Report feedback
The `getComputedTiming()` method of the `AnimationEffect` interface returns the calculated timing properties for this animation effect.

**Note:** These values are comparable to the computed styles of an Element returned using `window.getComputedStyle(elem)`.

Syntax
------

```js
getComputedTiming()
```

### Parameters

None.

### Return value

An object which contains:

* all of the properties of the object returned by `AnimationEffect.getTiming()`, except that any `"auto"` values are replaced by computed values that may depend on the type of `AnimationEffect`.
* the following additional properties:

`endTime`

A `number` indicating the end time of the effect in milliseconds from the effect's start. This is equal to `activeDuration` plus `delay` and `endDelay`.

`activeDuration`

A `number` indicating the total duration in milliseconds of all iterations of the effect. This is equal to `duration` multiplied by `iterations` (or zero if that product would be `NaN`).

`localTime`

A `number` or `null`.

Indicates the length of time in milliseconds that the effect has run. This is equal to the `currentTime` of the associated animation, or `null` if the effect is not associated with an animation.

`progress`

`null` or a `number` at least `0` and less than `1`.

Indicates the effect's progress through its current iteration. At the start of the `activeDuration`, this equals the fractional part of `iterationStart`.

Returns `null` if the effect isn't mid-iteration, for example because the effect is in the `delay` or `endDelay` periods, the effect is finished, or `localTime` is `null`.

`currentIteration`

`null` or an integer `number`.

Indicates the index of the current iteration. At the start of the `activeDuration`, this equals the integer part of `iterationStart`.

Returns `null` whenever `progress` is `null`.
Specifications
--------------

| Specification |
| --- |
| Web Animations # dom-animationeffect-getcomputedtiming |

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

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

See also
--------

* Web Animations API
* `AnimationEffect`
* `Animation`


DynamicsCompressorNode: attack property - Web APIs

DynamicsCompressorNode: attack property
=======================================

The `attack` property of the `DynamicsCompressorNode` interface is a k-rate `AudioParam` representing the amount of time, in seconds, required to reduce the gain by 10 dB. It defines how quickly the signal is adapted when its volume is increased.

The `attack` property's default value is `0.003` and it can be set between `0` and `1`.

Value
-----

An `AudioParam`.

**Note:** Though the `AudioParam` returned is read-only, the value it represents is not.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
compressor.attack.value = 0;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-attack |

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

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

See also
--------

* Using the Web Audio API


DynamicsCompressorNode: ratio property - Web APIs

DynamicsCompressorNode: ratio property
======================================

The `ratio` property of the `DynamicsCompressorNode` interface Is a k-rate `AudioParam` representing the amount of change, in dB, needed in the input for a 1 dB change in the output.

The `ratio` property's default value is `12` and it can be set between `1` and `20`.

![Describes the effect of different ratio on the output signal](/en-US/docs/Web/API/DynamicsCompressorNode/ratio/webaudioratio.png)

Value
-----

An `AudioParam`.

**Note:** Though the `AudioParam` returned is read-only, the value it represents is not.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
compressor.ratio.value = 12;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-ratio |

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

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

See also
--------

* Using the Web Audio API


DynamicsCompressorNode: DynamicsCompressorNode() constructor - Web APIs

DynamicsCompressorNode: DynamicsCompressorNode() constructor
============================================================

 The **`DynamicsCompressorNode()`**
 constructor creates a new `DynamicsCompressorNode` object which provides
 a compression effect, which lowers the volume of the loudest parts of the
 signal, in order to help prevent clipping and distortion. That can occur when
 multiple sounds are played and multiplexed together at once.

Syntax
------

```js
new DynamicsCompressorNode(context, options)
```

### Parameters

`context`

A reference to an `AudioContext`.

`options` Optional

Options are as follows:

`attack`

 The amount of time (in seconds) to reduce the gain by 10dB.
 Its default value is 0.003. This parameter is k-rate. Its nominal range is [0, 1].

`knee`

 A decibel value representing the range above the threshold
 where the curve smoothly transitions to the "ratio" portion. Its default value is
 30. This parameter is k-rate. Its nominal range is [0, 40].

`ratio`

 The amount of dB change in input for a 1 dB change in
 output. Its default value is 12. This parameter is k-rate. Its nominal range is
 [1, 20].

`release`

 The amount of time (in seconds) to increase the gain by 10dB. Its
 default value is 0.250. This parameter is k-rate. Its nominal range is [0, 1].

`threshold`

 The decibel value above which the compression will start taking
 effect. Its default value is -24. This parameter is k-rate. Its nominal range is
 [-100, 0].

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-constructor-dynamicscompressornode |

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

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


DynamicsCompressorNode: threshold property - Web APIs

DynamicsCompressorNode: threshold property
==========================================

The `threshold` property of the `DynamicsCompressorNode` interface is a k-rate `AudioParam` representing the decibel value above which the compression will start taking effect.

The `threshold` property's default value is `-24` and it can be set between `-100` and `0`.

![The threshold attribute has no effect on signals lowers than its value, but induce volume reduction on signal stronger than its value.](/en-US/docs/Web/API/DynamicsCompressorNode/threshold/webaudiothreshold.png)

Value
-----

An `AudioParam`.

**Note:** Though the `AudioParam` returned is read-only, the value it represents is not.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
compressor.threshold.value = -50;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-threshold |

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

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

See also
--------

* Using the Web Audio API


DynamicsCompressorNode: reduction property - Web APIs

DynamicsCompressorNode: reduction property
==========================================

The **`reduction`** read-only property of the `DynamicsCompressorNode` interface is a float representing the amount of gain reduction currently applied by the compressor to the signal.

Intended for metering purposes, it returns a value in dB, or `0` (no gain reduction) if no signal is fed into the `DynamicsCompressorNode`. The range of this value is between `-20` and `0` (in dB).

Value
-----

A float.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
const myReduction = compressor.reduction;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-reduction |

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

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

See also
--------

* Using the Web Audio API


DynamicsCompressorNode: release property - Web APIs

DynamicsCompressorNode: release property
========================================

The `release` property of the `DynamicsCompressorNode` interface Is a k-rate `AudioParam` representing the amount of time, in seconds, required to increase the gain by 10 dB. It defines how quick the signal is adapted when its volume is reduced.

The `release` property's default value is `0.25` and it can be set between `0` and `1`.

Value
-----

An `AudioParam`.

**Note:** Though the `AudioParam` returned is read-only, the value it represents is not.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
compressor.release.value = 0.25;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-release |

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

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

See also
--------

* Using the Web Audio API


DynamicsCompressorNode: knee property - Web APIs

DynamicsCompressorNode: knee property
=====================================

The `knee` property of the `DynamicsCompressorNode` interface is a k-rate `AudioParam` containing a decibel value representing the range above the threshold where the curve smoothly transitions to the compressed portion.

The `knee` property's default value is `30` and it can be set between `0` and `40`.

![Describes the effect of a knee, showing two curves one for a hard knee, the other for a soft knee.](/en-US/docs/Web/API/DynamicsCompressorNode/knee/webaudioknee.png)

Value
-----

An `AudioParam`.

**Note:** Though the `AudioParam` returned is read-only, the value it represents is not.

Examples
--------

```js
const audioCtx = new AudioContext();
const compressor = audioCtx.createDynamicsCompressor();
compressor.knee.value = 40;
```

See `BaseAudioContext.createDynamicsCompressor()` for more complete example code.

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

| Specification |
| --- |
| Web Audio API # dom-dynamicscompressornode-knee |

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

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

See also
--------

* Using the Web Audio API


SVGAnimatedString: baseVal property - Web APIs

SVGAnimatedString: baseVal property
===================================

BaseVal gets or sets the base value of the given attribute before any animations are applied. The base value of the given attribute before applying any animations. Setter throws DOMException.

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

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 2 # \_\_svg\_\_SVGAnimatedString\_\_baseVal |

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

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


SVGAnimatedString: animVal property - Web APIs

SVGAnimatedString: animVal property
===================================

AnimVal attribute or animVal property contains the same value as the `SVGAnimatedString.baseVal` property. If the given attribute or property is being animated, contains the current animated value of the attribute or property. If the given attribute or property is not currently being animated, then it contains the same value as baseVal

**Note:** The **animVal** property is a read only property.

Syntax
------

```js
const currentValue = object.animVal
```

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

| Specification |
| --- |
| Scalable Vector Graphics (SVG) 2 # \_\_svg\_\_SVGAnimatedString\_\_animVal |

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

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


DataTransfer: types property - Web APIs

DataTransfer: types property
============================

 The **`DataTransfer.types`** read-only property returns the available types
 that exist in the `items`.

Value
-----

 An array of the data formats used in the drag operation. Each format is a string
 which is generally a MIME type such as `text/plain` or `text/html`. If the drag
 operation included no data, this list will be empty. If any files are included in
 the drag operation, then one of the types will be the string `Files`.

Examples
--------

 This example shows the use of the `types` and
 `items` properties.

```html
<!doctype html>
<html lang="en">
  <title>Examples of DataTransfer.{types,items} properties</title>
  <meta content="width=device-width" />
  <style>
 div {
 margin: 0em;
 padding: 2em;
 }
 #target {
 border: 1px solid black;
 }
 </style>
  <script>
 function dragstart\_handler(ev) {
 console.log("dragStart: target.id = " + ev.target.id);

 // Add this element's id to the drag payload so the drop handler will
 // know which element to add to its tree
 ev.dataTransfer.setData("text/plain", ev.target.id);
 ev.dataTransfer.effectAllowed = "move";
 }

 function drop\_handler(ev) {
 console.log("drop: target.id = " + ev.target.id);
 ev.preventDefault();

 // Get the id of the target and add the moved element to the target's DOM
 const data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));

 // Print each format type
 for (let i = 0; i < ev.dataTransfer.types.length; i++) {
 console.log(`… types[${i}] = ${ev.dataTransfer.types[i]}`);
 }

 // Print each item's "kind" and "type"
 for (let i = 0; i < ev.dataTransfer.items.length; i++) {
 console.log(
 `… items[${i}].kind = ${ev.dataTransfer.items[i].kind}; type = ${ev.dataTransfer.items[i].type}`,
 );
 }
 }

 function dragover\_handler(ev) {
 console.log("dragOver");
 ev.preventDefault();
 // Set the dropEffect to move
 ev.dataTransfer.dropEffect = "move";
 }
 </script>
  <body>
    <h1>
      Examples of <code>DataTransfer</code>.{<code>types</code>,
      <code>items</code>} properties
    </h1>
    <ul>
      <li id="i1" ondragstart="dragstart\_handler(event);" draggable="true">
        Drag Item 1 to the Drop Zone
      </li>
      <li id="i2" ondragstart="dragstart\_handler(event);" draggable="true">
        Drag Item 2 to the Drop Zone
      </li>
    </ul>
    <div
 id="target"
 ondrop="drop\_handler(event);"
 ondragover="dragover\_handler(event);">
      Drop Zone
    </div>
  </body>
</html>
```

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-types-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: dropEffect property - Web APIs

DataTransfer: dropEffect property
=================================

 The **`DataTransfer.dropEffect`** property controls the
 feedback (typically visual) the user is given during a drag and drop operation. It will
 affect which cursor is displayed while dragging. For example, when the user hovers over
 a target drop element, the browser's cursor may indicate which type of operation will
 occur.

 When the `DataTransfer` object is created, `dropEffect` is set
 to a string value. On getting, it returns its current value. On setting, if the new
 value is one of the values listed below, then the property's current value will be set
 to the new value and other values will be ignored.

 For the `dragenter` and `dragover` events,
 `dropEffect` will be initialized based on what action the user is requesting.
 How this is determined is platform specific, but typically the user can press modifier
 keys such as the alt key to adjust the desired action. Within event handlers for
 `dragenter` and `dragover` events, `dropEffect` should
 be modified if a different action is desired than the action that the user is
 requesting.

 For the `drop` and `dragend` events, `dropEffect` will
 be set to the action that was desired, which will be the value `dropEffect`
 had after the last `dragenter` or `dragover` event. In a
 `dragend` event, for instance, if the desired dropEffect is "move", then the
 data being dragged should be removed from the source.

Value
-----

 A string representing the drag operation effect. The possible values
 are:

`copy`

A copy of the source item is made at the new location.

`move`

An item is moved to a new location.

`link`

A link is established to the source at the new location.

`none`

The item may not be dropped.

 Assigning any other value to `dropEffect` has no effect and the old value is
 retained.

Example
-------

 This example shows the use of the `dropEffect` and
 `effectAllowed` properties.

### HTML

```html
<div>
  <p id="source" ondragstart="dragstart\_handler(event);" draggable="true">
    Select this element, drag it to the Drop Zone and then release the selection
    to move the element.
  </p>
</div>
<div
 id="target"
 ondrop="drop\_handler(event);"
 ondragover="dragover\_handler(event);">
  Drop Zone
</div>
```

### CSS

```css
div {
  margin: 0em;
  padding: 2em;
}

#source {
  color: blue;
  border: 1px solid black;
}

#target {
  border: 1px solid black;
}
```

### JavaScript

```js
function dragstart\_handler(ev) {
  console.log(
    `dragStart: dropEffect = ${ev.dataTransfer.dropEffect} ; effectAllowed = ${ev.dataTransfer.effectAllowed}`,
  );

  // Add this element's id to the drag payload so the drop handler will
  // know which element to add to its tree
  ev.dataTransfer.setData("text", ev.target.id);
  ev.dataTransfer.effectAllowed = "move";
}

function drop\_handler(ev) {
  console.log(
    `drop: dropEffect = ${ev.dataTransfer.dropEffect} ; effectAllowed = ${ev.dataTransfer.effectAllowed}`,
  );
  ev.preventDefault();

  // Get the id of the target and add the moved element to the target's DOM
  const data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}

function dragover\_handler(ev) {
  console.log(
    `dragOver: dropEffect = ${ev.dataTransfer.dropEffect} ; effectAllowed = ${ev.dataTransfer.effectAllowed}`,
  );
  ev.preventDefault();
  // Set the dropEffect to move
  ev.dataTransfer.dropEffect = "move";
}
```

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-dropeffect-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: items property - Web APIs

DataTransfer: items property
============================

 The read-only `DataTransfer` property `items` property is a
 `list` of the data
 transfer items in a drag operation. The list includes one item for each item in the
 operation and if the operation had no items, the list is empty.

Value
-----

 A `DataTransferItemList` object containing `DataTransferItem`
 objects representing the items being dragged in a drag operation, one list item for each
 object being dragged. If the drag operation had no data, the list is empty.

Examples
--------

### Logging dragged items

This example uses `items` to log information about dragged items.

#### HTML

```html
<ul>
  <li id="source1" draggable="true">Drag Item 1 to the Drop Zone</li>
  <li id="source2" draggable="true">Drag Item 2 to the Drop Zone</li>
</ul>
<div id="target">Drop Zone</div>

<button id="reset">Reset</button>
```

#### CSS

```css
div {
  margin: 0em;
  padding: 2em;
}

#target {
  border: 1px solid black;
}
```

#### JavaScript

```js
function dragstartHandler(ev) {
  console.log(`dragstart: target.id = ${ev.target.id}`);
  // Add this element's id to the drag payload so the drop handler will
  // know which element to add to its tree
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dataTransfer.effectAllowed = "move";
}

function dropHandler(ev) {
  ev.preventDefault();
  // Get the id of the target and add the moved element to the target's DOM
  const data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
  // Print each item's "kind" and "type"
  if (ev.dataTransfer.items) {
    for (const item of ev.dataTransfer.items) {
      console.log(`kind = ${item.kind}, type = ${item.type}`);
    }
  }
}

function dragoverHandler(ev) {
  ev.preventDefault();
  // Set the dropEffect to move
  ev.dataTransfer.dropEffect = "move";
}

const source1 = document.querySelector("#source1");
const source2 = document.querySelector("#source2");
const target = document.querySelector("#target");

source1.addEventListener("dragstart", dragstartHandler);
source2.addEventListener("dragstart", dragstartHandler);
target.addEventListener("dragover", dragoverHandler);
target.addEventListener("drop", dropHandler);

const reset = document.querySelector("#reset");
reset.addEventListener("click", () => document.location.reload());
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-items-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: effectAllowed property - Web APIs

DataTransfer: effectAllowed property
====================================

 The **`DataTransfer.effectAllowed`** property specifies the
 effect that is allowed for a drag operation. The *copy* operation is used to
 indicate that the data being dragged will be copied from its present location to the
 drop location. The *move* operation is used to indicate that the data being
 dragged will be moved, and the *link* operation is used to indicate that some
 form of relationship or connection will be created between the source and drop
 locations.

 This property should be set in the `dragstart` event to set the desired drag
 effect for the drag source. Within the `dragenter` and `dragover`
 event handlers, this property will be set to whatever value was assigned during the
 `dragstart` event, thus `effectAllowed` may be used to determine
 which effect is permitted.

 Assigning a value to `effectAllowed` in events other than
 `dragstart` has no effect.

Value
-----

 A string representing the drag operation that is allowed. The
 possible values are:

`none`

The item may not be dropped.

`copy`

A copy of the source item may be made at the new location.

`copyLink`

A copy or link operation is permitted.

`copyMove`

A copy or move operation is permitted.

`link`

A link may be established to the source at the new location.

`linkMove`

A link or move operation is permitted.

`move`

An item may be moved to a new location.

`all`

All operations are permitted.

`uninitialized`

The default value when the effect has not been set, equivalent to all.

 Assigning any other value to `effectAllowed` has no effect and the old value
 is retained.

Examples
--------

### Setting effectAllowed

In this example we set `effectAllowed` to `"move"` in the `dragstart` handler.

#### HTML

```html
<div>
  <p id="source" draggable="true">
    Select this element, drag it to the Drop Zone and then release the selection
    to move the element.
  </p>
</div>
<div id="target">Drop Zone</div>
<pre id="output"></pre>
<button id="reset">Reset</button>
```

#### CSS

```css
div {
  margin: 0em;
  padding: 2em;
}

#source {
  color: blue;
  border: 1px solid black;
}

#target {
  border: 1px solid black;
}

#output {
  height: 100px;
  overflow: scroll;
}
```

#### JavaScript

```js
function dragstartHandler(ev) {
  log(`dragstart: effectAllowed = ${ev.dataTransfer.effectAllowed}`);

  // Add this element's id to the drag payload so the drop handler will
  // know which element to add to its tree
  ev.dataTransfer.setData("text", ev.target.id);
  ev.dataTransfer.effectAllowed = "move";
}

function dropHandler(ev) {
  log(`drop: effectAllowed = ${ev.dataTransfer.effectAllowed}`);

  ev.preventDefault();
  // Get the id of the target and add the element to the target's DOM
  const data = ev.dataTransfer.getData("text");
  ev.target.appendChild(document.getElementById(data));
}

function dragoverHandler(ev) {
  log(`dragover: effectAllowed = ${ev.dataTransfer.effectAllowed}`);
  ev.preventDefault();
}

const source = document.querySelector("#source");
const target = document.querySelector("#target");

source.addEventListener("dragstart", dragstartHandler);
target.addEventListener("dragover", dragoverHandler);
target.addEventListener("drop", dropHandler);

function log(message) {
  const output = document.querySelector("#output");
  output.textContent = `${output.textContent}\n${message}`;
  output.scrollTop = output.scrollHeight;
}

const reset = document.querySelector("#reset");
reset.addEventListener("click", () => document.location.reload());
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-effectallowed-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: setDragImage() method - Web APIs

DataTransfer: setDragImage() method
===================================

 When a drag occurs, a translucent image is generated from the drag target (the element
 the `dragstart` event is fired at), and follows the mouse pointer during the
 drag. This image is created automatically, so you do not need to create it yourself.
 However, if a custom image is desired, the
 **`DataTransfer.setDragImage()`** method can be used to set the
 custom image to be used. The image will typically be an `<img>` element
 but it can also be a `<canvas>` or any other visible element.

 The method's `x` and `y` coordinates define how the image should
 appear relative to the mouse pointer. These coordinates define the offset into the image
 where the mouse cursor should be. For instance, to display the image so that the pointer
 is at its center, use values that are half the width and height of the image.

This method must be called in the `dragstart` event handler.

Syntax
------

```js
setDragImage(imgElement, xOffset, yOffset)
```

### Parameters

`imgElement`

An image `Element` element to use for the drag feedback image.

 If `Element` is an img element, then set the drag data store bitmap to
 the element's image (at its intrinsic size); otherwise, set the drag data store bitmap
 to an image generated from the given element (the exact mechanism for doing so is not
 currently specified).

Note: If the `Element` is an existing `HTMLElement` it needs to be visible in the viewport in order to be shown as a drag feedback image. Alternatively, you can create a new DOM element that might be off-screen specifically for this purpose.

`xOffset`

A `long` indicating the horizontal offset within the image.

`yOffset`

A `long` indicating the vertical offset within the image.

### Return value

None (`undefined`).

Examples
--------

 This example shows how to use the `setDragImage()` method. Note the example
 refers to an image file named `example.gif`. If that file is present, it will
 be used as the drag image and if that file is not present, the browser will use its
 default drag image.

demo

```html
<!doctype html>
<html lang="en">
  <head>
    <title>Example of DataTransfer.setDragImage()</title>
    <meta name="viewport" content="width=device-width" />
    <style>
 div {
 margin: 0em;
 padding: 2em;
 }
 #source {
 color: blue;
 border: 1px solid black;
 }
 #target {
 border: 1px solid black;
 }
 </style>
    <script>
 function dragStartHandler(ev) {
 console.log("dragStart");
 // Set the drag's format and data. Use the event target's id for the data
 ev.dataTransfer.setData("text/plain", ev.target.id);
 // Create an image and use it for the drag image
 // NOTE: change "example.gif" to an existing image or the image will not
 // be created and the default drag image will be used.
 const img = new Image();
 img.src = "example.gif";
 ev.dataTransfer.setDragImage(img, 10, 10);
 }

 function dragOverHandler(ev) {
 console.log("dragOver");
 ev.preventDefault();
 }

 function dropHandler(ev) {
 console.log("Drop");
 ev.preventDefault();
 // Get the data, which is the id of the drop target
 const data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
 }
 </script>
  </head>
  <body>
    <h1>Example of <code>DataTransfer.setDragImage()</code></h1>
    <div>
      <p id="source" ondragstart="dragStartHandler(event);" draggable="true">
        Select this element, drag it to the Drop Zone and then release the
        selection to move the element.
      </p>
    </div>
    <div
 id="target"
 ondrop="dropHandler(event);"
 ondragover="dragOverHandler(event);">
      Drop Zone
    </div>
  </body>
</html>
```

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-setdragimage-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: files property - Web APIs

DataTransfer: files property
============================

The **`files`** read-only property of `DataTransfer` objects is a `list of the files` in the drag operation. If the operation includes no files, the list is empty.

This feature can be used to drag files from a user's desktop to the browser.

**Note:** The `files` property of `DataTransfer` objects can only be accessed from within the `drop` event. For all other events, the `files` property will be empty — because its underlying data store will be in a protected mode.

Value
-----

 A `list` of the files in a drag operation, one list item for
 each file in the operation. If the drag operation had no files, the list is empty.

Examples
--------

There are two live examples of this interface:

* Firefox only: https://jsfiddle.net/9C2EF/
* All browsers: https://jsbin.com/hiqasek/
Specifications
--------------

| Specification |
| --- |
| HTML Standard # dom-datatransfer-files-dev |

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

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


DataTransfer: getData() method - Web APIs

DataTransfer: getData() method
==============================

 The **`DataTransfer.getData()`**
 method retrieves drag data (as a string) for the specified type.
 If the drag operation does not include data, this method returns an empty
 string.

Example data types are `text/plain` and `text/uri-list`.

Syntax
------

```js
getData(format)
```

### Parameters

`format`

A string representing the type of data to retrieve.

### Return value

A string representing the drag data for the specified `format`. If the drag operation has no data or the operation has no data for the specified `format`, this method returns an empty string.

### Caveats

Data availability

 The HTML Drag and Drop Specification dictates a `drag data store mode`.
 This may result in unexpected behavior, being
 **`DataTransfer.getData()`** not returning an expected
 value, because not all browsers enforce this restriction.

During the `dragstart` and `drop` events, it is safe to access the data. For all other events, the data should be considered unavailable. Despite this, the items and their formats can still be enumerated.

Examples
--------

 This example shows the use of the `DataTransfer` object's
 `getData()` and
 `setData()` methods.

### HTML

```html
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
  <span id="drag" draggable="true" ondragstart="drag(event)"
 >drag me to the other box</span
 >
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
```

### CSS

```css
#div1,
#div2 {
  width: 100px;
  height: 50px;
  padding: 10px;
  border: 1px solid #aaaaaa;
}
```

### JavaScript

```js
function allowDrop(allowdropevent) {
  allowdropevent.target.style.color = "blue";
  allowdropevent.preventDefault();
}

function drag(dragevent) {
  dragevent.dataTransfer.setData("text", dragevent.target.id);
  dragevent.target.style.color = "green";
}

function drop(dropevent) {
  dropevent.preventDefault();
  const data = dropevent.dataTransfer.getData("text");
  dropevent.target.appendChild(document.getElementById(data));
  document.getElementById("drag").style.color = "black";
}
```

### Result

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-getdata-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: clearData() method - Web APIs

DataTransfer: clearData() method
================================

 The **`DataTransfer.clearData()`** method removes the drag
 operation's `drag data` for the given type. If data for the
 given type does not exist, this method does nothing.

 If this method is called with no arguments or the format is an empty
 string, the data of all types will be removed.

 This method does *not* remove files from the drag operation, so it's possible
 for there still to be an entry with the type `"Files"` left in the object's
 `DataTransfer.types` list if there are any files included in the drag.

**Note:** This method can only be used in the handler for the `dragstart` event,
 because that's the only time the drag operation's data store is writable.

Syntax
------

```js
clearData()
clearData(format)
```

### Parameters

`format` Optional

 A string which specifies the type of data to remove. If
 this parameter is an empty string or is not provided, the data for all types is
 removed.

### Return value

None (`undefined`).

Examples
--------

 This example shows the use of the `DataTransfer` object's
 `getData()`,
 `setData()` and
 `clearData()` methods.

### HTML

```html
<span class="tweaked" id="source" draggable="true">
  Select this element, drag it to the Drop Zone and then release the selection
  to move the element.
</span>
<span class="tweaked" id="target">Drop Zone</span>
<div>Status: <span id="status">Drag to start</span></div>
<div>Data is: <span id="data">uninitialized</span></div>
```

### CSS

```css
span.tweaked {
  display: inline-block;
  margin: 1em 0;
  padding: 1em 2em;
}

#source {
  color: blue;
  border: 1px solid black;
}

#target {
  border: 1px solid black;
}
```

### JavaScript

```js
window.addEventListener("DOMContentLoaded", () => {
  // Select HTML elements
  const draggable = document.getElementById("source");
  const droppable = document.getElementById("target");
  const status = document.getElementById("status");
  const data = document.getElementById("data");
  let dropped = false;

  // Register event handlers
  draggable.addEventListener("dragstart", dragStartHandler);
  draggable.addEventListener("dragend", dragEndHandler);
  droppable.addEventListener("dragover", dragOverHandler);
  droppable.addEventListener("dragleave", dragLeaveHandler);
  droppable.addEventListener("drop", dropHandler);

  function dragStartHandler(event) {
    status.textContent = "Drag in process";

    // Change target element's border to signify drag has started
    event.currentTarget.style.border = "1px dashed blue";

    // Start by clearing existing clipboards; this will affect all types since we
    // don't give a specific type.

    event.dataTransfer.clearData();

    // Set the drag's format and data (use event target's id for data)
    event.dataTransfer.setData("text/plain", event.target.id);

    data.textContent = event.dataTransfer.getData("text/plain");
  }

  function dragEndHandler(event) {
    if (!dropped) {
      status.textContent = "Drag canceled";
    }

    data.textContent = event.dataTransfer.getData("text/plain") || "empty";

    // Change border to signify drag is no longer in process
    event.currentTarget.style.border = "1px solid black";

    if (dropped) {
      // Remove all event listeners
      draggable.removeEventListener("dragstart", dragStartHandler);
      draggable.removeEventListener("dragend", dragEndHandler);
      droppable.removeEventListener("dragover", dragOverHandler);
      droppable.removeEventListener("dragleave", dragLeaveHandler);
      droppable.removeEventListener("drop", dropHandler);
    }
  }

  function dragOverHandler(event) {
    status.textContent = "Drop available";

    event.preventDefault();
  }

  function dragLeaveHandler(event) {
    status.textContent = "Drag in process (drop was available)";

    event.preventDefault();
  }

  function dropHandler(event) {
    dropped = true;

    status.textContent = "Drop done";

    event.preventDefault();

    // Get data linked to event format « text »
    const _data = event.dataTransfer.getData("text/plain");
    const element = document.getElementById(_data);

    // Append drag source element to event's target element
    event.target.appendChild(element);

    // Change CSS styles and displayed text
    element.style.cssText =
      "border: 1px solid black;display: block; color: red";
    element.textContent = "I'm in the Drop Zone!";
  }
});
```

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-cleardata-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: addElement() method - Web APIs

DataTransfer: addElement() method
=================================

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

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

 The **`DataTransfer.addElement()`** method sets the drag source
 to the given element. This element will be the element to which `drag` and
 `dragend` events are fired, and not the default target (the node that was
 dragged).

**Note:** This method is Firefox-specific.

Syntax
------

```js
addElement(element)
```

### Parameters

`element`

The `Element` to set as the drag source.

### Return value

None (`undefined`).

Examples
--------

This example shows the use of the `addElement()` method

```js
function change\_drag\_node(event, node) {
  const dt = event.dataTransfer;
  dt.addElement(node);
}
```

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

This method is not defined in any Web standard.

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


DataTransfer: DataTransfer() constructor - Web APIs

DataTransfer: DataTransfer() constructor
========================================

 The **`DataTransfer`** constructor creates a new
 `DataTransfer` object instance.

Syntax
------

```js
new DataTransfer()
```

### Parameters

None.

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-dev |

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

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


DataTransfer: setData() method - Web APIs

DataTransfer: setData() method
==============================

 The **`DataTransfer.setData()`** method sets the drag
 operation's `drag data` to the specified data and type. If
 data for the given type does not exist, it is added at the end of the drag data store,
 such that the last item in the `types` list will be
 the new type. If data for the given type already exists, the existing data is replaced
 in the same position. That is, the order of the
 `types` list is not changed when replacing data of the
 same type.

Example data types are `text/plain` and `text/uri-list`.

Syntax
------

```js
setData(format, data)
```

### Parameters

`format`

 A string representing the type of the drag data to add to the
 `drag object`.

`data`

 A string representing the data to add to the
 `drag object`.

### Return value

None (`undefined`).

Examples
--------

### Dragging an element

In this example we can drag a `<p>` element into a target `<div>` element.

* In the `dragstart` handler, we use `setData()` to add the `id` of the `<p>` element to the `DataTransfer` object.
* In the `drop` handler we retrieve the `id` and use it to move the `<p>` element into the target.

#### HTML

```html
<div>
  <p id="source" draggable="true">
    Select this element, drag it to the drop zone and then release the selection
    to move the element.
  </p>
</div>
<div id="target">Drop Zone</div>

<button id="reset">Reset example</button>
```

#### CSS

```css
div {
  margin: 0.5em 0;
  padding: 2em;
}

#target,
#source {
  border: 1px solid black;
  padding: 0.5rem;
}

.dragging {
  background-color: pink;
}
```

#### JavaScript

```js
const source = document.querySelector("#source");
source.addEventListener("dragstart", (ev) => {
  console.log("dragStart");
  // Change the source element's background color
  // to show that drag has started
  ev.currentTarget.classList.add("dragging");
  // Clear the drag data cache (for all formats/types)
  ev.dataTransfer.clearData();
  // Set the drag's format and data.
  // Use the event target's id for the data
  ev.dataTransfer.setData("text/plain", ev.target.id);
});
source.addEventListener("dragend", (ev) =>
  ev.target.classList.remove("dragging"),
);

const target = document.querySelector("#target");
target.addEventListener("dragover", (ev) => {
  console.log("dragOver");
  ev.preventDefault();
});
target.addEventListener("drop", (ev) => {
  console.log("Drop");
  ev.preventDefault();
  // Get the data, which is the id of the source element
  const data = ev.dataTransfer.getData("text");
  const source = document.getElementById(data);
  ev.target.appendChild(source);
});

const reset = document.querySelector("#reset");
reset.addEventListener("click", () => document.location.reload());
```

#### Result

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

| Specification |
| --- |
| HTML Standard # dom-datatransfer-setdata-dev |

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

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

See also
--------

* Drag and drop
* Drag Operations
* Recommended Drag Types
* DataTransfer test - Paste or Drag


CSSCounterStyleRule: name property - Web APIs

CSSCounterStyleRule: name property
==================================

The **`name`** property of the `CSSCounterStyleRule` interface gets and sets the `<custom-ident>` defined as the `name` for the associated rule.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `name` gives us the custom ident "box-corner".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
  fallback: disc;
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].name); // "box-corner"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-name |

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

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


CSSCounterStyleRule: symbols property - Web APIs

CSSCounterStyleRule: symbols property
=====================================

The **`symbols`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `symbols` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `symbols` gives us the value "◰ ◳ ◲ ◱".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
  negative: "-";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].symbols); // "◰ ◳ ◲ ◱"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-symbols |

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

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


CSSCounterStyleRule: speakAs property - Web APIs

CSSCounterStyleRule: speakAs property
=====================================

The **`speakAs`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `speak-as` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `speakAs` gives us the value "bullets".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
  speak-as: bullets;
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].speakAs); // "bullets"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-speakas |

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

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


CSSCounterStyleRule: prefix property - Web APIs

CSSCounterStyleRule: prefix property
====================================

The **`prefix`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `prefix` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `prefix` gives us the value "Chapter ".

```css
@counter-style chapters {
  system: numeric;
  symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
  prefix: "Chapter ";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].prefix); // "Chapter "
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-prefix |

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

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


CSSCounterStyleRule: pad property - Web APIs

CSSCounterStyleRule: pad property
=================================

The **`pad`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `pad` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `pad` gives us the value "0".

```css
@counter-style box-corner {
  system: numeric;
  symbols: "0" "1" "2" "3" "4" "5";
  pad: 2 "0";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].pad); // "0"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-pad |

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

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


CSSCounterStyleRule: additiveSymbols property - Web APIs

CSSCounterStyleRule: additiveSymbols property
=============================================

The **`additiveSymbols`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `additive-symbols` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string.

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `additiveSymbols` gives us the value " V 5, IV 4, I 1".

```css
@counter-style additive-symbols-example {
  system: additive;
  additive-symbols:
    V 5,
    IV 4,
    I 1;
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].additiveSymbols); // " V 5, IV 4, I 1"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-additivesymbols |

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

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


CSSCounterStyleRule: range property - Web APIs

CSSCounterStyleRule: range property
===================================

The **`range`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `range` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `range` gives us the value "2 4, 7 9".

```css
@counter-style range-multi-example {
  system: cyclic;
  symbols: "\25A0" "\25A1";
  range:
    2 4,
    7 9;
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].range); // "2 4, 7 9"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-range |

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

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


CSSCounterStyleRule: fallback property - Web APIs

CSSCounterStyleRule: fallback property
======================================

The **`fallback`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `fallback` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string.

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `fallback` gives us the value "disc".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
  fallback: disc;
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].fallback); // "disc"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-fallback |

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

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


CSSCounterStyleRule: suffix property - Web APIs

CSSCounterStyleRule: suffix property
====================================

The **`suffix`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `suffix` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `suffix` gives us the value ": ".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
  negative: "-";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].suffix); // ": "
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-suffix |

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

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


CSSCounterStyleRule: negative property - Web APIs

CSSCounterStyleRule: negative property
======================================

The **`negative`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `negative` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `negative` gives us the value "-".

```css
@counter-style neg {
  system: numeric;
  symbols: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
  negative: "-";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].negative); // "-"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-negative |

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

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


CSSCounterStyleRule: system property - Web APIs

CSSCounterStyleRule: system property
====================================

The **`system`** property of the `CSSCounterStyleRule` interface gets and sets the value of the `system` descriptor. If the descriptor does not have a value set, this attribute returns an empty string.

Value
-----

A string

Examples
--------

The following example shows a `@counter-style` rule. In JavaScript, `myRules[0]` is this `@counter-style` rule, returning `system` gives us the value "fixed".

```css
@counter-style box-corner {
  system: fixed;
  symbols: ◰ ◳ ◲ ◱;
  suffix: ": ";
}
```

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].system); // "fixed"
```

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

| Specification |
| --- |
| CSS Counter Styles Level 3 # dom-csscounterstylerule-system |

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

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


AudioWorkletNode: parameters property - Web APIs

AudioWorkletNode: parameters property
=====================================

 The read-only **`parameters`** property of the
 `AudioWorkletNode` interface returns the associated
 `AudioParamMap` — that is, a `Map`-like collection of
 `AudioParam` objects. They are instantiated during creation of the
 underlying `AudioWorkletProcessor` according to its
 `parameterDescriptors` static
 getter.

Value
-----

 The `AudioParamMap` object containing `AudioParam` instances.
 They can be automated in the same way as with default `AudioNode`s, and their
 calculated values can be used in the `process` method of your `AudioWorkletProcessor`.

Examples
--------

 To demonstrate creation and usage of custom `AudioParam`s, we'll expand the
 example from `AudioWorkletNode` page. There we've created a simple node
 which outputs white noise. Here, additionally, we'll create a custom gain parameter, so
 we can directly change volume of the output (although you could use
 `GainNode` to achieve this as well).

 First, we need to define a custom `AudioWorkletProcessor`, and register it.
 Note that this should be done in a separate file.

 We expand the processor by adding a static
 `parameterDescriptors`
 getter. It will be used internally by the `AudioWorkletNode` constructor to
 populate its `parameters` with instantiated `AudioParam` objects.

```js
// white-noise-processor.js
class WhiteNoiseProcessor extends AudioWorkletProcessor {
  static get parameterDescriptors() {
    return [
      {
        name: "customGain",
        defaultValue: 1,
        minValue: 0,
        maxValue: 1,
        automationRate: "a-rate",
      },
    ];
  }

  process(inputs, outputs, parameters) {
    const output = outputs[0];
    output.forEach((channel) => {
      for (let i = 0; i < channel.length; i++) {
        channel[i] =
          (Math.random() \* 2 - 1) \*
          (parameters["customGain"].length > 1
            ? parameters["customGain"][i]
            : parameters["customGain"][0]);
        // note: a parameter contains an array of 128 values (one value for each of 128 samples),
        // however it may contain a single value which is to be used for all 128 samples
        // if no automation is scheduled for the moment.
      }
    });
    return true;
  }
}

registerProcessor("white-noise-processor", WhiteNoiseProcessor);
```

 Next, in our main scripts file we'll load the processor, create an instance of
 `AudioWorkletNode` passing it the name of the processor, and connect the node
 to an audio graph.

```js
const audioContext = new AudioContext();
await audioContext.audioWorklet.addModule("white-noise-processor.js");
const whiteNoiseNode = new AudioWorkletNode(
  audioContext,
  "white-noise-processor",
);
whiteNoiseNode.connect(audioContext.destination);
```

Now we can change the gain on the node like this:

```js
const gainParam = whiteNoiseNode.parameters.get("customGain");
gainParam.setValueAtTime(0, audioContext.currentTime);
gainParam.linearRampToValueAtTime(0.5, audioContext.currentTime + 0.5);
```

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

| Specification |
| --- |
| Web Audio API # dom-audioworkletnode-parameters |

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

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

See also
--------

* Web Audio API
* Using the Web Audio API


AudioWorkletNode: port property - Web APIs

AudioWorkletNode: port property
===============================

 The read-only **`port`** property of the
 `AudioWorkletNode` interface returns the associated
 `MessagePort`. It can be used to communicate between the node and its
 associated `AudioWorkletProcessor`.

**Note:** The port at the other end of the channel is
 available under the `port` property of the
 processor.

Value
-----

 The `MessagePort` object that is connecting the
 `AudioWorkletNode` and its associated `AudioWorkletProcessor`.

Examples
--------

 To demonstrate bidirectional communication capabilities, we'll create an
 `AudioWorkletProcessor`, which will output silence and respond to ping
 requests from its `AudioWorkletNode`.

 First, we need to define a custom `AudioWorkletProcessor`, and register it.
 Note that this should be done in a separate file.

```js
// ping-pong-processor.js
class PingPongProcessor extends AudioWorkletProcessor {
  constructor(...args) {
    super(...args);
    this.port.onmessage = (e) => {
      console.log(e.data);
      this.port.postMessage("pong");
    };
  }
  process(inputs, outputs, parameters) {
    return true;
  }
}

registerProcessor("ping-pong-processor", PingPongProcessor);
```

 Now in our main scripts file we'll load the processor, create an instance of
 `AudioWorkletNode` passing the name of the processor, and connect the node to
 an audio graph.

```js
const audioContext = new AudioContext();
await audioContext.audioWorklet.addModule("ping-pong-processor.js");
const pingPongNode = new AudioWorkletNode(audioContext, "ping-pong-processor");
// send the message containing 'ping' string
// to the AudioWorkletProcessor from the AudioWorkletNode every second
setInterval(() => pingPongNode.port.postMessage("ping"), 1000);
pingPongNode.port.onmessage = (e) => console.log(e.data);
pingPongNode.connect(audioContext.destination);
```

 This will output `"ping"` and `"pong"` strings to the console
 every second.

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

| Specification |
| --- |
| Web Audio API # dom-audioworkletnode-port |

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

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

See also
--------

* Web Audio API
* Using the Web Audio API