IDBCursor: primaryKey property - Web APIs

IDBCursor: primaryKey property
==============================

 The **`primaryKey`** read-only property of the
 `IDBCursor` interface returns the cursor's current effective key. If the
 cursor is currently being iterated or has iterated outside its range, this is set to
 undefined. The cursor's primary key can be any data type.

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

Value
-----

A value of any data type.

Examples
--------

 In this simple fragment we create a transaction, retrieve an object store, then use a
 cursor to iterate through all the records in the object store. Within each iteration we
 log the primary key of the cursor to the console, something like this (its the album
 title in each case, which is our primarykey):
```

Hemispheres
```

 The cursor does not require us to select the data based
 on a key; we can just grab all of it. Also note that in each iteration of the loop,
 you can grab data from the current record under the cursor object using `cursor.value.foo`. For a complete working example, see our IDBCursor example (View the example live).

```js
function displayData() {
  const transaction = db.transaction(["rushAlbumList"], "readonly");
  const objectStore = transaction.objectStore("rushAlbumList");

  objectStore.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      const listItem = document.createElement("li");
      listItem.textContent = `${cursor.value.albumTitle}, ${cursor.value.year}`;
      list.appendChild(listItem);

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

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

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbcursor-primarykey① |

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

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

See also
--------

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


IDBCursor: key property - Web APIs

IDBCursor: key property
=======================

 The **`key`** read-only property of the
 `IDBCursor` interface returns the key for the record at the cursor's
 position. If the cursor is outside its range, this is set to undefined. The cursor's
 key can be any data type.

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

Value
-----

A value of any type.

Examples
--------

 In this simple fragment we create a transaction, retrieve an object store, then use a
 cursor to iterate through all the records in the object store. Within each iteration we
 log the key of the cursor to the console, something like this (its the album title in
 each case, which is our key).

 The cursor does not require us to select the data based
 on a key; we can just grab all of it. Also note that in each iteration of the loop,
 you can grab data from the current record under the cursor object using `cursor.value.foo`. For a complete working example, see our IDBCursor example (View the example live).

```js
function displayData() {
  const transaction = db.transaction(["rushAlbumList"], "readonly");
  const objectStore = transaction.objectStore("rushAlbumList");

  objectStore.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      const listItem = document.createElement("li");
      listItem.textContent = `${cursor.value.albumTitle}, ${cursor.value.year}`;
      list.appendChild(listItem);

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

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

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbcursor-key① |

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

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

See also
--------

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


IDBCursor: continue() method - Web APIs

IDBCursor: continue() method
============================

 The **`continue()`** method of the `IDBCursor`
 interface advances the cursor to the next position along its direction, to the item
 whose key matches the optional key parameter. If no key is specified, the cursor
 advances to the immediate next position, based on its direction.

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

Syntax
------

```js
continue()
continue(key)
```

### Parameters

`key` Optional

The key to position the cursor at.

### Return value

None (`undefined`).

### Exceptions

This method may raise a `DOMException` of one of the following types:

`TransactionInactiveError` `DOMException`

Thrown if this IDBCursor's transaction is inactive.

`DataError` `DOMException`

Thrown if the key parameter has any of the following conditions:

* The key is not a valid key.
* The key is less than or equal to this cursor's position, and the cursor's direction is `next` or `nextunique`.
* The key is greater than or equal to this cursor's position and this cursor's direction is `prev` or `prevunique`.

`InvalidStateError` `DOMException`

Thrown if the cursor is currently being iterated or has iterated past its end.

Examples
--------

 In this simple fragment we create a transaction, retrieve an object store, then use a
 cursor to iterate through all the records in the object store. The cursor does not
 require us to select the data based on a key; we can just grab all of it. Also note that
 in each iteration of the loop, you can grab data from the current record under the
 cursor object using `cursor.value.foo`. For a complete working example, see
 our IDBCursor example (View the example live).

```js
function displayData() {
  const transaction = db.transaction(["rushAlbumList"], "readonly");
  const objectStore = transaction.objectStore("rushAlbumList");

  objectStore.openCursor().onsuccess = (event) => {
    const cursor = event.target.result;
    if (cursor) {
      const listItem = document.createElement("li");
      listItem.textContent = `${cursor.value.albumTitle}, ${cursor.value.year}`;
      list.appendChild(listItem);

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

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

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbcursor-continue① |

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

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

See also
--------

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


Drag operations - Web APIs

Drag operations
===============

The following describes the steps that occur during a drag and drop operation.

The drag operations described in this document use the `DataTransfer` interface. This document does *not* use the `DataTransferItem` interface nor the `DataTransferItemList` interface.

The draggable attribute
-----------------------

In a web page, there are certain cases where a default drag behavior is used. These include text selections, images, and links. When an image or link is dragged, the URL of the image or link is set as the drag data, and a drag begins. For other elements, they must be part of a selection for a default drag to occur. To see this in effect, select an area of a webpage, and then click and hold the mouse and drag the selection. An OS-specific rendering of the selection will appear and follow the mouse pointer as the drag occurs. However, this behavior is only the default drag behavior, if no listeners adjust the data to be dragged.

In HTML, apart from the default behavior for images, links, and selections, no other elements are draggable by default.

To make other HTML elements draggable, three things must be done:

1. Set the `draggable` attribute to `"true"` on the element that you wish to make draggable.
2. Add a listener for the `dragstart` event.
3. Set the drag data in the above listener.

Here is an example which allows a section of content to be dragged.

```html
<p draggable="true">This text <strong>may</strong> be dragged.</p>
```

```js
const draggableElement = document.querySelector('p[draggable="true"]');

draggableElement.addEventListener("dragstart", (event) =>
  event.dataTransfer.setData("text/plain", "This text may be dragged"),
);
```

The `draggable` attribute is set to `"true"`, so this element becomes draggable. If this attribute were omitted or set to `"false"`, the element would not be dragged, and instead the text would be selected.

The `draggable` attribute may be used on any element, including images and links. However, for these last two, the default value is `true`, so you would only use the `draggable` attribute with a value of `false` to disable dragging of these elements.

**Note:** When an element is made draggable, text or other elements within it can no longer be selected in the normal way by clicking and dragging with the mouse. Instead, the user must hold down the `Alt` key to select text with the mouse, or use the keyboard.

Starting a drag operation
-------------------------

In this example, we add a listener for the `dragstart` event by using the `addEventListener()` method.

```html
<p draggable="true">This text <strong>may</strong> be dragged.</p>
```

```js
const draggableElement = document.querySelector('p[draggable="true"]');
draggableElement.addEventListener("dragstart", (event) =>
  event.dataTransfer.setData("text/plain", "This text may be dragged"),
);
```

When a user begins to drag, the `dragstart` event is fired.

In this example the `dragstart` listener is added to the draggable element itself. However, you could listen to a higher ancestor as drag events bubble up as most other events do.

Within the `dragstart` event, you can specify the **drag data**, the **feedback image**, and the **drag effects**, all of which are described below. However, only the **drag data** is required. (The default image and drag effects are suitable in most situations.)

Drag data
---------

All `drag events` have a property called `dataTransfer` which holds the drag data (`dataTransfer` is a `DataTransfer` object).

When a drag occurs, data must be associated with the drag which identifies *what* is being dragged. For example, when dragging the selected text within a textbox, the data associated with the *drag data item* is the text itself. Similarly, when dragging a link on a web page, the drag data item is the link's URL.

The `drag data` contains two pieces of information, the **type** (or format) of the data, and the data's **value**. The format is a type string (such as `text/plain` for text data), and the value is a string of text. When the drag begins, you add data by providing a type and the data. During the drag, in an event listener for the `dragenter` and `dragover` events, you use the data types of the data being dragged to check whether a drop is allowed. For instance, a drop target that accepts links would check for the type `text/uri-list`. During a drop event, a listener would retrieve the data being dragged and insert it at the drop location.

The `drag data's` `types` property returns a list of MIME-type like strings, such as `text/plain` or `image/jpeg`. You can also create your own types. The most commonly used types are listed in the article Recommended Drag Types.

A drag may include data items of several different types. This allows data to be provided in more specific types, often custom types, yet still provide fallback data for drop targets that do not support more specific types. It is usually the case that the least specific type will be normal text data using the type `text/plain`. This data will be a simple textual representation.

To set a drag data item within the `dataTransfer`, use the `setData()` method. It takes two arguments: the type of data and the data value. For example:

```js
event.dataTransfer.setData("text/plain", "Text to drag");
```

In this case, the data value is "Text to drag" and is of the format `text/plain`.

You can provide data in multiple formats. To do this, call the `setData()` method multiple times with different formats. You should call it with formats in order from most specific to least specific.

```js
const dt = event.dataTransfer;
dt.setData("application/x.bookmark", bookmarkString);
dt.setData("text/uri-list", "https://www.mozilla.org");
dt.setData("text/plain", "https://www.mozilla.org");
```

Here, data is added in three different types. The first type, `application/x.bookmark`, is a custom type. Other applications won't support this type, but you can use a custom type for drags between areas of the same site or application.

By providing data in other types as well, we can also support drags to other applications in less specific forms. The `application/x.bookmark` type can provide data with more details for use within the application whereas the other types can include just a single URL or text version.

Note that both the `text/uri-list` and `text/plain` contain the same data in this example. This will often be true, but doesn't need to be the case.

If you attempt to add data twice with the same format, the new data will replace the old data, but in the same position within the list of types as the old data.

You can clear the data using the `clearData()` method, which takes one argument: the type of the data to remove.

```js
event.dataTransfer.clearData("text/uri-list");
```

The `type` argument to the `clearData()` method is optional. If the `type` is not specified, the data associated with all types is removed. If the drag contains no drag data items, or all of the items have been subsequently cleared, then no drag will occur.

Setting the drag feedback image
-------------------------------

When a drag occurs, a translucent image is generated from the drag target (the element the "`dragstart`" event is fired at), and follows the user's pointer during the drag. This image is created automatically, so you do not need to create it yourself. However, you can use `setDragImage()` to specify a custom drag feedback image.

```js
event.dataTransfer.setDragImage(image, xOffset, yOffset);
```

Three arguments are necessary. The first is a reference to an image. This reference will typically be to an `<img>` element, but it can also be to a `<canvas>` or any other element. The feedback image will be generated from whatever the image looks like on screen, although for images, they will be drawn at their original size. The second and third arguments to the `setDragImage()` method are offsets where the image should appear relative to the mouse pointer.

It is also possible to use images and canvases that are not in a document. This technique is useful when drawing custom drag images using the canvas element, as in the following example:

```js
function dragWithCustomImage(event) {
  const canvas = document.createElement("canvas");
  canvas.width = canvas.height = 50;

  const ctx = canvas.getContext("2d");
  ctx.lineWidth = 4;
  ctx.moveTo(0, 0);
  ctx.lineTo(50, 50);
  ctx.moveTo(0, 50);
  ctx.lineTo(50, 0);
  ctx.stroke();

  const dt = event.dataTransfer;
  dt.setData("text/plain", "Data to Drag");
  dt.setDragImage(canvas, 25, 25);
}
```

In this example, we make one canvas the drag image. As the canvas is `50`×`50` pixels, we use offsets of half of this (`25`) so that the image appears centered on the mouse pointer.

Drag effects
------------

When dragging, there are several operations that may be performed. 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.

You can specify which of the three operations are allowed for a drag source by setting the `effectAllowed` property within a `dragstart` event listener.

```js
event.dataTransfer.effectAllowed = "copy";
```

In this example, only a **copy** is allowed.

You can combine the values in various ways:

`none`

no operation is permitted

`copy`

`copy` only

`move`

`move` only

`link`

`link` only

`copyMove`

`copy` or `move` only

`copyLink`

`copy` or `link` only

`linkMove`

`link` or `move` only

`all`

`copy`, `move`, or `link`

uninitialized

The default value is `all`.

Note that these values must be used exactly as listed above. For example, setting the `effectAllowed` property to `copyMove` allows a copy or move operation but prevents the user from performing a link operation. If you don't change the `effectAllowed` property, then any operation is allowed, just like with the '`all`' value. So you don't need to adjust this property unless you want to exclude specific types.

During a drag operation, a listener for the `dragenter` or `dragover` events can check the `effectAllowed` property to see which operations are permitted. A related property, `dropEffect`, should be set within one of these events to specify which single operation should be performed. Valid values for `dropEffect` are `none`, `copy`, `move`, or `link`. The combination values are not used for this property.

With the `dragenter` and `dragover` event, the `dropEffect` property is initialized to the effect that the user is requesting. The user can modify the desired effect by pressing modifier keys. Although the exact keys used vary by platform, typically the `Shift` and `Control` keys would be used to switch between copying, moving, and linking. The mouse pointer will change to indicate which operation is desired. For instance, for a `copy`, the cursor might appear with a plus sign next to it.

You can modify the `dropEffect` property during the `dragenter` or `dragover` events, if for example, a particular drop target only supports certain operations. You can modify the `dropEffect` property to override the user effect, and enforce a specific drop operation to occur. Note that this effect must be one listed within the `effectAllowed` property. Otherwise, it will be set to an alternate value that is allowed.

```js
event.dataTransfer.dropEffect = "copy";
```

In this example, copy is the effect that is performed.

You can use the value `none` to indicate that no drop is allowed at this location, although it is preferred not to cancel the event in this case.

Within the `drop` and `dragend` events, you can check the `dropEffect` property to determine which effect was ultimately chosen. If the chosen effect were "`move`", then the original data should be removed from the source of the drag within the `dragend` event.

Specifying drop targets
-----------------------

A listener for the `dragenter` and `dragover` events are used to indicate valid drop targets, that is, places where dragged items may be dropped. Most areas of a web page or application are not valid places to drop data. Thus, the default handling of these events is not to allow a drop.

If you want to allow a drop, you must prevent the default behavior by cancelling both the `dragenter` and `dragover` events. You can do this by calling their `preventDefault()` methods:

```html
<div id="drop-target">You can drag and then drop a draggable item here</div>
```

```js
const dropElement = document.getElementById("drop-target");

dropElement.addEventListener("dragenter", (event) => {
  event.preventDefault();
});

dropElement.addEventListener("dragover", (event) => {
  event.preventDefault();
});
```

Calling the `preventDefault()` method during both a `dragenter` and `dragover` event will indicate that a drop is allowed at that location. However, you will commonly wish to call the `preventDefault()` method only in certain situations (for example, only if a link is being dragged).

To do this, call a function which checks a condition and only cancels the event when the condition is met. If the condition is not met, don't cancel the event, and a drop will not occur there if the user releases the mouse button.

It is most common to accept or reject a drop based on the type of drag data in the data transfer — for instance, allowing images, or links, or both. To do this, you can check the `types` property of the event's `dataTransfer` (property). The `types` property returns an array of the string types that were added when the drag began, in the order from most significant to least significant.

```js
function doDragOver(event) {
  const isLink = event.dataTransfer.types.includes("text/uri-list");
  if (isLink) {
    event.preventDefault();
  }
}
```

In this example, we use the `includes` method to check if the type `text/uri-list` is present in the list of types. If it is, we will cancel the event so that a drop may be allowed. If the drag data does not contain a link, the event will not be cancelled, and a drop cannot occur at that location.

You may also wish to set either the `effectAllowed`, `dropEffect` property, or both at the same time, if you wish to be more specific about the type of operation that will performed. Naturally, changing either property will have no effect if you do not cancel the event as well.

Drop feedback
-------------

There are several ways in which you can indicate to the user that a drop is allowed at a certain location. The mouse pointer will update as necessary depending on the value of the `dropEffect` property.

Although the exact appearance depends on the user's platform, typically a plus sign icon will appear for a '`copy`' for example, and a 'cannot drop here' icon will appear when a drop is not allowed. This mouse pointer feedback is sufficient in many cases.

For more complex visual effects, you can perform other operations during the `dragenter` event. For example, by inserting an element at the location where the drop will occur. This might be an insertion marker, or an element that represents the dragged element in its new location. To do this, you could create an `<img>` element and insert it into the document during the `dragenter` event.

The `dragover` event will fire at the element the mouse is pointing at. Naturally, you may need to move the insertion marker around a `dragover` event as well. You can use the event's `clientX` and `clientY` properties as with other mouse events to determine the location of the mouse pointer.

Finally, the `dragleave` event will fire at an element when the drag leaves the element. This is the time when you should remove any insertion markers or highlighting. You do not need to cancel this event. The `dragleave` event will always fire, even if the drag is cancelled, so you can always ensure that any insertion point cleanup can be done during this event.

Performing a drop
-----------------

When the user releases the mouse, the drag and drop operation ends.

If the mouse is released over an element that is a valid drop target, that is, one that cancelled the last `dragenter` or `dragover` event, then the drop will be successful, and a `drop` event will fire at the target. Otherwise, the drag operation is cancelled, and no `drop` event is fired.

During the `drop` event, you should retrieve that data that was dropped from the event and insert it at the drop location. You can use the `dropEffect` property to determine which drag operation was desired.

As with all drag-related events, the event's `dataTransfer` property will hold the data that is being dragged. The `getData()` method may be used to retrieve the data again.

```js
function onDrop(event) {
  const data = event.dataTransfer.getData("text/plain");
  event.target.textContent = data;
  event.preventDefault();
}
```

The `getData()` method takes one argument, the type of data to retrieve. It will return the string value that was set when `setData()` was called at the beginning of the drag operation. An empty string will be returned if data of that type does not exist. (Naturally, though, you would likely know that the right type of data was available, as it was previously checked during a `dragover` event.)

In the example here, once the data has been retrieved, we insert the string as the textual content of the target. This has the effect of inserting the dragged text where it was dropped, assuming that the drop target is an area of text such as a `p` or `div` element.

In a web page, you should call the `preventDefault()` method of the event if you have accepted the drop, so that the browser's default handling is not triggered by the dropped data as well. For example, when a link is dragged to a web page, Firefox will open the link. By cancelling the event, this behavior will be prevented.

You can retrieve other types of data as well. If the data is a link, it should have the type `text/uri-list`. You could then insert a link into the content.

```js
function doDrop(event) {
  const lines = event.dataTransfer.getData("text/uri-list").split("\n");
  lines
    .filter((line) => !line.startsWith("#"))
    .forEach((line) => {
      const link = document.createElement("a");
      link.href = line;
      link.textContent = line;
      event.target.appendChild(link);
    });
  event.preventDefault();
}
```

This example inserts a link from the dragged data. As the name implies, the `text/uri-list` type actually may contain a list of URLs, each on a separate line. The above code uses `split` to break the string into lines, then iterates over the list of lines, and inserts each as a link into the document. (Note also that links starting with a number sign (`#`) are skipped, as these are comments.)

For simple cases, you can use the special type `URL` just to retrieve the first valid URL in the list. For example:

```js
const link = event.dataTransfer.getData("URL");
```

This eliminates the need to check for comments or iterate through lines yourself. However, it is limited to only the first URL in the list.

The `URL` type is a special type. It is used only as a shorthand, and it does not appear within the list of types specified in the `types` property.

Sometimes you may support some different formats, and you want to retrieve the data that is most specific that is supported. In the following example, three formats are supported by a drop target.

The following example returns the data associated with the best-supported format:

```js
function doDrop(event) {
  const supportedTypes = [
    "application/x-moz-file",
    "text/uri-list",
    "text/plain",
  ];
  const types = event.dataTransfer.types.filter((type) =>
    supportedTypes.includes(type),
  );
  if (types.length) {
    const data = event.dataTransfer.getData(types[0]);
    // Use this type of data…
  }
  event.preventDefault();
}
```

Finishing a drag
----------------

Once the drag is complete, a `dragend` event is fired at the source of the drag (the same element that received the `dragstart` event). This event will fire if the drag was successful or if it was cancelled. However, you can use the `dropEffect` property to determine which drop operation occurred.

If the `dropEffect` property has the value `none` during a `dragend`, then the drag was cancelled. Otherwise, the effect specifies which operation was performed. The source can use this information after a `move` operation to remove the dragged item from the old location.

A drop can occur inside the same window or over another application. The `dragend` event will always fire regardless. The event's `screenX` and `screenY` properties will be set to the screen coordinates where the drop occurred.

After the `dragend` event has finished propagating, the drag and drop operation is complete.

See also
--------

* HTML Drag and Drop API (Overview)
* Recommended Drag Types
* HTML Living Standard: Drag and Drop


File drag and drop - Web APIs

File drag and drop
==================

HTML Drag and Drop interfaces enable web applications to drag and drop files on a web page. This document describes how an application can accept one or more files that are dragged from the underlying platform's *file manager* and dropped on a web page.

The main steps to drag and drop are to define a *drop zone* (i.e. a target element for the file drop) and to define event handlers for the `drop` and `dragover` events. These steps are described below, including example code snippets. The full source code is available in MDN's drag-and-drop repository (pull requests and/or issues are welcome).

Note that `HTML drag and drop` defines two different APIs to support dragging and dropping files. One API is the `DataTransfer` interface and the second API is the `DataTransferItem` and `DataTransferItemList` interfaces. This example illustrates the use of both APIs (and does not use any Gecko specific interfaces).

Define the drop zone
--------------------

The *target element* of the `drop` event needs an `ondrop` event handler. The following code snippet shows how this is done with a `<div>` element:

```html
<div id="drop\_zone" ondrop="dropHandler(event);">
  <p>Drag one or more files to this <i>drop zone</i>.</p>
</div>
```

Typically, an application will include a `dragover` event handler on the drop target element and that handler will turn off the browser's default drag behavior. To add this handler, you need to include a `ondragover` event handler:

```html
<div
 id="drop\_zone"
 ondrop="dropHandler(event);"
 ondragover="dragOverHandler(event);">
  <p>Drag one or more files to this <i>drop zone</i>.</p>
</div>
```

Lastly, an application may want to style the drop target element to visually indicate the element is a drop zone. In this example, the drop target element uses the following styling:

```css
#drop\_zone {
  border: 5px solid blue;
  width: 200px;
  height: 100px;
}
```

**Note:** `dragstart` and `dragend` events are not fired when dragging a file into the browser from the OS. To detect when OS files are dragged into the browser, use `dragenter` and `dragleave`.
 This means that it is not possible to use `setDragImage()` to apply a custom drag image/cursor overlay when dragging files from the OS — because the drag data store can only be modified in the `dragstart` event. This also applies to `setData()`.

Process the drop
----------------

The `drop` event is fired when the user drops the file(s). In the following drop handler, if the browser supports `DataTransferItemList` interface, the `getAsFile()` method is used to access each file; otherwise the `DataTransfer` interface's `files` property is used to access each file.

This example shows how to write the name of each dragged file to the console. In a *real* application, an application may want to process a file using the `File API`.

Note that in this example, any drag item that is not a file is ignored.

```js
function dropHandler(ev) {
  console.log("File(s) dropped");

  // Prevent default behavior (Prevent file from being opened)
  ev.preventDefault();

  if (ev.dataTransfer.items) {
    // Use DataTransferItemList interface to access the file(s)
    [...ev.dataTransfer.items].forEach((item, i) => {
      // If dropped items aren't files, reject them
      if (item.kind === "file") {
        const file = item.getAsFile();
        console.log(`… file[${i}].name = ${file.name}`);
      }
    });
  } else {
    // Use DataTransfer interface to access the file(s)
    [...ev.dataTransfer.files].forEach((file, i) => {
      console.log(`… file[${i}].name = ${file.name}`);
    });
  }
}
```

Prevent the browser's default drag behavior
-------------------------------------------

The following `dragover` event handler calls `preventDefault()` to turn off the browser's default drag and drop handler.

```js
function dragOverHandler(ev) {
  console.log("File(s) in drop zone");

  // Prevent default behavior (Prevent file from being opened)
  ev.preventDefault();
}
```

See also
--------

* HTML Drag and Drop API
* Drag Operations
* HTML Living Standard: Drag and Drop


Recommended Drag Types - Web APIs

Recommended Drag Types
======================

The HTML Drag and Drop API supports dragging various types of data, including plain text, URLs, HTML code, files, etc. The document describes best practices for common draggable data types.

Dragging Text
-------------

For dragging text, use the `text/plain` type. The second data parameter should be the dragged string. For example:

```js
event.dataTransfer.setData("text/plain", "This is text to drag");
```

Dragging text in textboxes and selections on web pages is done automatically by the browser, so you do not need to handle it yourself.

It is recommended to always add data of the `text/plain` type as a fallback for applications or drop targets that do not support other types, unless there is no logical text alternative. Always add this `text/plain` type last, as it is the least specific and shouldn't be preferred.

Note: In older code, you may find `text/unicode` or the `Text` types. These are equivalent to `text/plain`, and will store and retrieve plain text data.

Dragging Links
--------------

Dragged hyperlinks should include data of two types: `text/uri-list`, and `text/plain`. *Both* types should use the link's URL for their data. For example:

```js
const dt = event.dataTransfer;
dt.setData("text/uri-list", "https://www.mozilla.org");
dt.setData("text/plain", "https://www.mozilla.org");
```

As usual, set the `text/plain` type last, as a fallback for the `text/uri-list` type.

Note: the URL type is `uri-list` with an *I*, not an *L*.

To drag multiple links, separate each link inside the `text/uri-list` data with a CRLF linebreak. Lines that begin with a number sign (`#`) are comments, and should not be considered URLs. You can use comments to indicate the purpose of a URL, the title associated with a URL, or other data.

**Warning:** The `text/plain` fallback for multiple links should include all URLs, but no comments.

For example, this sample `text/uri-list` data contains two links and a comment:
```

http://www.mozilla.org
#A second link
http://www.example.com
```

When retrieving a dropped link, ensure you handle when multiple links are dragged, including any comments. For convenience, the special type `URL` may be used to refer to the first valid link within data for the `text/uri-list` type.

**Warning:** Do not add data with the `URL` type — attempting to do so will set the value of the `text/uri-list` type instead.

```js
const url = event.dataTransfer.getData("URL");
```

You may also see data with the Mozilla-specific type `text/x-moz-url`. If it appears, it should appear before the `text/uri-list` type. It holds the URLs of links followed by their titles, separated by a linebreak. For example:
```

http://www.mozilla.org
Mozilla
http://www.example.com
Example
```

Dragging HTML and XML
---------------------

HTML content may use the `text/html` type. The data for this type should be serialized HTML source code. For example, it would be suitable to set its data to the value of the `innerHTML` property of an element.

XML content may use the `text/xml` type, but ensure that the data is well-formed XML.

You may also include a plain text representation of the HTML or XML data using the `text/plain` type. The data should be just the text without any of the source tags or attributes. For instance:

```js
const dt = event.dataTransfer;
dt.setData("text/html", "Hello there, <strong>stranger</strong>");
dt.setData("text/plain", "Hello there, stranger");
```

### Updates to DataTransfer.types

The latest spec dictates that `DataTransfer.types` should return a frozen array of strings rather than a `DOMStringList` (this is supported in Firefox 52 and above).

As a result, the contains method no longer works; the includes method should be used instead to check if a specific type of data is provided, using code like the following:

```js
if ([...event.dataTransfer.types].includes("text/html")) {
  // Do something
}
```

You could use feature detection to determine which method is supported on `types`, then run code as appropriate.

Dragging Images
---------------

Direct image dragging is not common. In fact, Mozilla does not support direct image dragging on Mac or Linux. Instead, images are usually dragged only by their URLs. To do this, use the `text/uri-list` type as with other URLs. The data should be the URL of the image, or a `data:` URL if the image is not stored on a website or disk.

As with links, the data for the `text/plain` type should also contain the URL. However, a `data:` URL is not usually useful in a text context, so you may wish to exclude the `text/plain` data in this situation.

In chrome or other privileged code, you may also use the `image/jpeg`, `image/png` or `image/gif` types, depending on the type of image. The data should be an object which implements the `nsIInputStream` interface. When this stream is read, it should provide the data bits for the image, as if the image was a file of that type.

You should also include the `application/x-moz-file` type if the image is located on disk. In fact, this a common way in which image files are dragged.

It is important to set the data in the right order, from most-specific to least-specific. The standard image type, such as `image/jpeg`, should come first, followed by the `application/x-moz-file` type. Next, you should set the `text/uri-list` data, and finally the `text/plain` data. For example:

```js
const dt = event.dataTransfer;
dt.setData("text/uri-list", imageurl);
dt.setData("text/plain", imageurl);
```

Dragging Nodes
--------------

Nodes and elements in a document may be dragged using the `application/x-moz-node` type. The data for the type should be a DOM node. This allows the drop target to receive the actual node where the drag was started from. Note that callers from a different domain will not be able to access the node even when it has been dropped.

You should always include a `text/plain` alternative for the node.

Dragging Custom Data
--------------------

You can also use other types that you invent for custom purposes. Strive to always include a `text/plain` alternative, unless the dragged object is specific to a particular site or application. In this case, the custom type ensures that the data cannot be dropped elsewhere.

Dragging files to an operating system folder
--------------------------------------------

You may want to add a file to an existing drag event session, and you may also want to write the file to disk when the drop operation happens over a folder in the operating system when your code receives notification of the target folder's location. This only works in extensions (or other privileged code) and the type `application/moz-file-promise` should be used. The following sample offers an overview of this advanced case:

```js
// currentEvent is an existing drag operation event

currentEvent.dataTransfer.setData("text/x-moz-url", URL);
currentEvent.dataTransfer.setData("application/x-moz-file-promise-url", URL);
currentEvent.dataTransfer.setData(
  "application/x-moz-file-promise-dest-filename",
  leafName,
);

function dataProvider() {}

dataProvider.prototype = {
  QueryInterface(iid) {
    if (
      iid.equals(Components.interfaces.nsIFlavorDataProvider) ||
      iid.equals(Components.interfaces.nsISupports)
    )
      return this;
    throw Components.results.NS\_NOINTERFACE;
  },
  getFlavorData(aTransferable, aFlavor, aData, aDataLen) {
    if (aFlavor === "application/x-moz-file-promise") {
      const urlPrimitive = {};
      const dataSize = {};

      aTransferable.getTransferData(
        "application/x-moz-file-promise-url",
        urlPrimitive,
        dataSize,
      );
      const url = urlPrimitive.value.QueryInterface(
        Components.interfaces.nsISupportsString,
      ).data;
      console.log(`URL file original is = ${url}`);

      const namePrimitive = {};
      aTransferable.getTransferData(
        "application/x-moz-file-promise-dest-filename",
        namePrimitive,
        dataSize,
      );
      const name = namePrimitive.value.QueryInterface(
        Components.interfaces.nsISupportsString,
      ).data;

      console.log(`target filename is = ${name}`);

      const dirPrimitive = {};
      aTransferable.getTransferData(
        "application/x-moz-file-promise-dir",
        dirPrimitive,
        dataSize,
      );
      const dir = dirPrimitive.value.QueryInterface(
        Components.interfaces.nsILocalFile,
      );

      console.log(`target folder is = ${dir.path}`);

      const file = Cc["@mozilla.org/file/local;1"].createInstance(
        Components.interfaces.nsILocalFile,
      );
      file.initWithPath(dir.path);
      file.appendRelativePath(name);

      console.log(`output final path is = ${file.path}`);

      // now you can write or copy the file yourself…
    }
  },
};
```

See also
--------

* HTML Drag and Drop API (Overview)
* Drag Operations
* HTML Living Standard: Drag and Drop


Permissions: query() method - Web APIs

Permissions: query() method
===========================

The **`Permissions.query()`** method of the `Permissions` interface returns the state of a user permission on the global scope.

Syntax
------

```js
query(permissionDescriptor)
```

### Parameters

`permissionDescriptor`

An object that sets options for the `query` operation consisting of a comma-separated list of name-value pairs. The available options are:

`name`

The name of the API whose permissions you want to query. Each browser supports a different set of values. You'll find Firefox values there, Chromium values there, and WebKit values there.

`userVisibleOnly`

(Push only, not supported in Firefox — see the Browser Support section below) Indicates whether you want to show a notification for every message or be able to send silent push notifications. The default is `false`.

`sysex` (Midi only)

Indicates whether you need and/or receive system exclusive messages. The default is `false`.

**Note:** As of Firefox 44, the permissions for Notifications and Push have been merged. If permission is granted (e.g. by the user, in the relevant permissions dialog), `navigator.permissions.query()` will return `true` for both `notifications` and `push`.

**Note:** The `persistent-storage` permission allows an origin to use a persistent box (i.e., persistent storage) for its storage, as per the Storage API.

### Return value

A `Promise` that resolves to a `PermissionStatus` object.

### Exceptions

`InvalidStateError` `DOMException`

Thrown if `query()` method is invoked in the browsing context and its associated document is not fully active.

`TypeError`

Thrown if retrieving the `PermissionDescriptor` information failed in some way, or the permission doesn't exist or is unsupported by the user agent.

Examples
--------

```js
navigator.permissions.query({ name: "geolocation" }).then((result) => {
  if (result.state === "granted") {
    showLocalNewsWithGeolocation();
  } else if (result.state === "prompt") {
    showButtonToEnableLocalNews();
  }
  // Don't do anything if the permission was denied.
});
```

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

| Specification |
| --- |
| Permissions # dom-permissions-query |

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

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


Permissions: revoke() method - Web APIs

Permissions: revoke() method
============================

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

 The **`Permissions.revoke()`** method of the
 `Permissions` interface reverts a currently set permission back to its
 default state, which is usually `prompt`.
 This method is called on the global `Permissions` object
 `navigator.permissions`.

Syntax
------

```js
revoke(descriptor)
```

### Parameters

`descriptor`

 An object based on the `PermissionDescriptor` dictionary that sets
 options for the operation consisting of a comma-separated list of name-value pairs.
 The available options are:

`name`

 The name of the API whose permissions you want to query.
 Valid values are `'geolocation'`, `'midi'`,
 `'notifications'`, and `'push'`.

`userVisibleOnly`

 (Push only, not supported in Firefox — see the
 Browser compatibility section below) Indicates whether you want to
 show a notification for every message or be able to send silent push
 notifications. The default is `false`.

`sysex` (MIDI only)

 Indicates whether you need and/or receive system
 exclusive messages. The default is `false`.

**Note:** As of Firefox 44, the permissions for Notifications and Push have been merged. If permission is
 granted (e.g. by the user, in the relevant permissions dialog),
 `navigator.permissions.query()` will return `true` for both
 `notifications` and `push`.

**Note:** The `persistent-storage` permission allows an
 origin to use a persistent box (i.e., persistent storage) for its
 storage, as per the Storage API.

### Return value

 A `Promise` that calls its fulfillment handler with a
 `PermissionStatus` object indicating the result of the request.

### Exceptions

`TypeError`

 Retrieving the `PermissionDescriptor` information failed in some way, or
 the permission doesn't exist or is currently unsupported (e.g. `midi`, or
 `push` with `userVisibleOnly`).

Examples
--------

 This function can be used by an app to request that its own Geolocation API permission
 be revoked.

```js
function revokePermission() {
  navigator.permissions.revoke({ name: "geolocation" }).then((result) => {
    report(result.state);
  });
}
```

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

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


Event: stopImmediatePropagation() method - Web APIs

Event: stopImmediatePropagation() method
========================================

 The **`stopImmediatePropagation()`** method of the
 `Event` interface prevents other listeners of the same event from being called.

If several listeners are attached to the same element for the same event type, they are called in the order in which they were added. If `stopImmediatePropagation()` is invoked during one such call, no remaining listeners will be called, either on that element or any other element.

Syntax
------

```js
event.stopImmediatePropagation()
```

Examples
--------

### Comparing event-stopping functions

The example below has three buttons inside of three nested divs. Each button has three event listeners registered for click events, and each div has an event listener, also registered for click events.

* The top button allows normal event propagation.
* The middle button calls `stopPropagation()` in its first event handler.
* The bottom button calls `stopImmediatePropagation()` in its first event handler.

#### HTML

```html
<h2>Click on the buttons</h2>
<div>
  outer div<br />
  <div>
    middle div<br />
    <div>
      inner div<br />
      <button>allow propagation</button><br />
      <button id="stopPropagation">stop propagation</button><br />
      <button id="stopImmediatePropagation">immediate stop propagation</button>
    </div>
  </div>
</div>
<pre></pre>
```

#### CSS

```css
div {
  display: inline-block;
  padding: 10px;
  background-color: #fff;
  border: 2px solid #000;
  margin: 10px;
}

button {
  width: 100px;
  color: #008;
  padding: 5px;
  background-color: #fff;
  border: 2px solid #000;
  border-radius: 30px;
  margin: 5px;
}
```

#### JavaScript

```js
const outElem = document.querySelector("pre");

/\* Clear the output \*/
document.addEventListener(
  "click",
  () => {
    outElem.textContent = "";
  },
  true,
);

/\* Set event listeners for the buttons \*/
document.querySelectorAll("button").forEach((elem) => {
  for (let i = 1; i <= 3; i++) {
    elem.addEventListener("click", (evt) => {
      /\* Do any propagation stopping in first event handler \*/
      if (i === 1 && elem.id) {
        evt[elem.id]();
        outElem.textContent += `Event handler for event 1 calling ${elem.id}()\n`;
      }

      outElem.textContent += `Click event ${i} processed on "${elem.textContent}" button\n`;
    });
  }
});

/\* Set event listeners for the divs \*/
document
  .querySelectorAll("div")
  .forEach((elem) =>
    elem.addEventListener(
      "click",
      (evt) =>
        (outElem.textContent += `Click event processed on "${elem.firstChild.data.trim()}"\n`),
    ),
  );
```

#### Result

Each click-event handler displays a status message when it is called. If you press the middle button, you will see that `stopPropagation()` allows all of the event handlers registered for clicks on that button to execute but prevents execution of the click-event handlers for the divs, which would normally follow. However, if you press the bottom button, `stopImmediatePropagation()` stops all propagation after the event that called it.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-stopimmediatepropagation① |

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

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


Event: preventDefault() method - Web APIs

Event: preventDefault() method
==============================

The **`preventDefault()`** method of the `Event` interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

 The event continues to propagate as usual,
 unless one of its event listeners calls
 `stopPropagation()`
 or `stopImmediatePropagation()`,
 either of which terminates propagation at once.

 As noted below, calling **`preventDefault()`** for a
 non-cancelable event, such as one dispatched via
 `EventTarget.dispatchEvent()`, without specifying
 `cancelable: true` has no effect.

Syntax
------

```js
event.preventDefault()
```

Examples
--------

### Blocking default click handling

 Toggling a checkbox is the default action of clicking on a checkbox. This example
 demonstrates how to prevent that from happening:

#### JavaScript

```js
const checkbox = document.querySelector("#id-checkbox");

checkbox.addEventListener("click", checkboxClick, false);

function checkboxClick(event) {
  let warn = "preventDefault() won't let you check this!<br>";
  document.getElementById("output-box").innerHTML += warn;
  event.preventDefault();
}
```

#### HTML

```html
<p>Please click on the checkbox control.</p>

<form>
  <label for="id-checkbox">Checkbox:</label>
  <input type="checkbox" id="id-checkbox" />
</form>

<div id="output-box"></div>
```

#### Result

### Stopping keystrokes from reaching an edit field

 The following example demonstrates how invalid text input can be stopped from reaching
 the input field with `preventDefault()`. Nowadays, you should usually use native HTML form validation
 instead.

#### HTML

 The HTML form below captures user input.
 Since we're only interested in keystrokes, we're disabling `autocomplete` to prevent the browser from filling in the input field with cached values.

```html
<div class="container">
  <p>Please enter your name using lowercase letters only.</p>

  <form>
    <input type="text" id="my-textbox" autocomplete="off" />
  </form>
</div>
```

#### CSS

 We use a little bit of CSS for the warning box we'll draw when the user presses an
 invalid key:

```css
.warning {
  border: 2px solid #f39389;
  border-radius: 2px;
  padding: 10px;
  position: absolute;
  background-color: #fbd8d4;
  color: #3b3c40;
}
```

#### JavaScript

 And here's the JavaScript code that does the job. First, listen for
 `keydown` events:

```js
const myTextbox = document.getElementById("my-textbox");
myTextbox.addEventListener("keydown", checkName, false);
```

 The `checkName()` function, which looks at the pressed key and decides
 whether to allow it:

```js
function checkName(evt) {
  const key = evt.key;
  const lowerCaseAlphabet = "abcdefghijklmnopqrstuvwxyz";
  if (!lowerCaseAlphabet.includes(key)) {
    evt.preventDefault();
    displayWarning(
      "Please use lowercase letters only.\n" + `Key pressed: ${key}\n`,
    );
  }
}
```

 The `displayWarning()` function presents a notification of a problem. It's
 not an elegant function but does the job for the purposes of this example:

```js
let warningTimeout;
const warningBox = document.createElement("div");
warningBox.className = "warning";

function displayWarning(msg) {
  warningBox.innerHTML = msg;

  if (document.body.contains(warningBox)) {
    clearTimeout(warningTimeout);
  } else {
    // insert warningBox after myTextbox
    myTextbox.parentNode.insertBefore(warningBox, myTextbox.nextSibling);
  }

  warningTimeout = setTimeout(() => {
    warningBox.parentNode.removeChild(warningBox);
    warningTimeout = -1;
  }, 2000);
}
```

#### Result

Notes
-----

 Calling `preventDefault()` during any stage of event flow cancels the event,
 meaning that any default action normally taken by the implementation as a result of the
 event will not occur.

 You can use `Event.cancelable` to check if the event is cancelable.
 Calling `preventDefault()` for a non-cancelable event has no effect.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-preventdefault③ |

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

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


Event: explicitOriginalTarget property - Web APIs

Event: explicitOriginalTarget 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.

The read-only **`explicitOriginalTarget`** property of the `Event` interface returns the non-anonymous original target of the event.

If the event was retargeted for some reason other than an anonymous boundary crossing, this will be set to the target before the retargeting occurs.

For example, mouse events are retargeted to their parent node when they happen over text nodes (see Firefox bug 185889), and in that case `currentTarget` will show the parent while this property will show the text node.

This property also differs from `originalTarget` in that it will never contain anonymous content.

Value
-----

Returns the `EventTarget` object, or null if there isn't one.

Example
-------

This property can be used with `<command>` to get the event details of the original object calling the command.

```js
function myCommand(ev) {
  alert(ev.explicitOriginalTarget.nodeName); // returns 'menuitem'
}
```

```xml
<xul:command id="my-cmd-anAction" oncommand="myCommand(event);"/>

<xul:menulist>
  <xul:menupopup>
    <xul:menuitem label="Get my element name!" command="my-cmd-anAction"/>
  </xul:menupopup>
</menulist>
```

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

*This is a Mozilla-specific property and is not part of any current specification. It is not on track to become a standard.*

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

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

See also
--------

* Comparison of Event Targets


Event: initEvent() method - Web APIs

Event: initEvent() method
=========================

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

 The **`Event.initEvent()`** method is used to initialize the
 value of an `event` created using `Document.createEvent()`.

 Events initialized in this way must have been created with the
 `Document.createEvent()` method.
 This method must be called to set the event
 before it is dispatched, using `EventTarget.dispatchEvent()`.
 Once dispatched, it doesn't do anything anymore.

**Note:** *Do not use this method anymore as it is deprecated.*
 Instead use specific event constructors, like `Event()`.
 The page on Creating and triggering events gives more information about the way to use these.

Syntax
------

```js
event.initEvent(type, bubbles, cancelable)
```

### Parameters

`type`

A string defining the type of event.

`bubbles`

 A boolean value deciding whether the event should bubble up through the
 event chain or not. Once set, the read-only property `Event.bubbles`
 will give its value.

`cancelable`

 A boolean value defining whether the event can be canceled. Once set, the
 read-only property `Event.cancelable` will give its value.

Return value
------------

None.

Example
-------

```js
// Create the event.
const event = document.createEvent("Event");

// Create a click event that bubbles up and
// cannot be canceled
event.initEvent("click", true, false);

// Listen for the event.
elem.addEventListener(
  "click",
  (e) => {
    // e.target matches elem
  },
  false,
);

elem.dispatchEvent(event);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-initevent① |

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

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

See also
--------

* The constructor to use instead of this deprecated method:
 `Event()`. To create more specific event interfaces than `Event`, use the constructor defined for the desired event interface.


Comparison of Event Targets - Web APIs

Comparison of Event Targets
===========================

It's easy to get confused about which event target to examine when writing an event handler. This article should clarify the use of the target properties.

There are five targets to consider:

| Property | Defined in | Purpose |
| --- | --- | --- |
| `event.target` | DOM Event Interface |
 The DOM element on the left-hand side of the call that triggered this
 event.
  |
| `event.currentTarget` | DOM Event Interface |
 The
 `EventTarget`
 whose
 `EventListeners`
 are currently being processed. As the event capturing and bubbling
 occurs, this value changes.
  |
| `event.relatedTarget` | DOM MouseEvent Interface | Identifies a secondary target for the event. |
| `event.explicitOriginalTarget` | Event.webidl |
Non-standard
 If the event was retargeted for
 some reason other than an anonymous boundary crossing, this will be set
 to the target before the retargeting occurs. For example, mouse events
 are retargeted to their parent node when they happen over text nodes
 ([Firefox bug 185889](https://bugzil.la/185889)), and in that case `.target` will
 show the parent and `.explicitOriginalTarget` will show the
 text node.Unlike `.originalTarget`,
 `.explicitOriginalTarget` will never contain anonymous
 content.
  |
| `event.originalTarget` | Event.webidl |
Non-standard
 The original target of the event,
 before any retargetings. See
 Anonymous Content#Event\_Flow\_and\_Targeting
 for details.
  |
| event.composedTarget | Event.webidl |
Non-standard
 The original non-native target of
 the event before composition from Shadow DOM.
  |

### Use of `explicitOriginalTarget` and `originalTarget`

**Note:** These properties are only available in Mozilla-based browsers.

### Examples

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Comparison of Event Targets</title>
    <style>
 table {
 border-collapse: collapse;
 height: 150px;
 width: 100%;
 }
 td {
 border: 1px solid #ccc;
 font-weight: bold;
 padding: 5px;
 min-height: 30px;
 }
 .standard {
 background-color: #99ff99;
 }
 .non-standard {
 background-color: #902d37;
 }
 </style>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <td class="standard">
            Original target dispatching the event <small>event.target</small>
          </td>
          <td class="standard">
            Target who's event listener is being processed
            <small>event.currentTarget</small>
          </td>
          <td class="standard">
            Identify other element (if any) involved in the event
            <small>event.relatedTarget</small>
          </td>
          <td class="non-standard">
            If there was a retargeting of the event for some reason
            <small> event.explicitOriginalTarget</small> contains the target
            before retargeting (never contains anonymous targets)
          </td>
          <td class="non-standard">
            If there was a retargeting of the event for some reason
            <small> event.originalTarget</small> contains the target before
            retargeting (may contain anonymous targets)
          </td>
        </tr>
      </thead>
      <tr>
        <td id="target"></td>
        <td id="currentTarget"></td>
        <td id="relatedTarget"></td>
        <td id="explicitOriginalTarget"></td>
        <td id="originalTarget"></td>
      </tr>
    </table>
    <p>
      Clicking on the text will show the difference between
      explicitOriginalTarget, originalTarget, and target
    </p>
    <script>
 function handleClicks(e) {
 document.getElementById("target").innerHTML = e.target;
 document.getElementById("currentTarget").innerHTML = e.currentTarget;
 document.getElementById("relatedTarget").innerHTML = e.relatedTarget;
 document.getElementById("explicitOriginalTarget").innerHTML =
 e.explicitOriginalTarget;
 document.getElementById("originalTarget").innerHTML = e.originalTarget;
 }

 function handleMouseover(e) {
 document.getElementById("target").innerHTML = e.target;
 document.getElementById("relatedTarget").innerHTML = e.relatedTarget;
 }

 document.addEventListener("click", handleClicks, false);
 document.addEventListener("mouseover", handleMouseover, false);
 </script>
  </body>
</html>
```

### Use of `target` and `relatedTarget`

The `relatedTarget` property for the `mouseover` event holds the node that the mouse was previously over. For the `mouseout` event, it holds the node that the mouse moved to.

| Event type | event.target | event.relatedTarget |
| --- | --- | --- |
| `mouseover` | the EventTarget which the pointing device entered | the EventTarget which the pointing device exited |
| `mouseout` | the EventTarget which the pointing device exited | the EventTarget which the pointing device entered |

#### Example

```xml
<hbox id="outer">
  <hbox id="inner"
 onmouseover="dump('mouseover ' + event.relatedTarget.id + ' > ' + event.target.id + '\n');"
 onmouseout="dump('mouseout ' + event.target.id + ' > ' + event.relatedTarget.id + '\n');"
 style="margin: 100px; border: 10px solid black; width: 100px; height: 100px;" />
</hbox>
```


Event: type property - Web APIs

Event: type property
====================

 The **`type`** read-only property of the `Event`
 interface returns a string containing the event's type. It is set when the event is
 constructed and is the name commonly used to refer to the specific event, such as
 `click`, `load`, or `error`.

Value
-----

A string containing the type of `Event`.

Example
-------

 This example logs the event type whenever you press a keyboard key or click a mouse
 button.

### HTML

```html
<p>Press any key or click the mouse to get the event type.</p>
<p id="log"></p>
```

### JavaScript

```js
function getEventType(event) {
  const log = document.getElementById("log");
  log.innerText = `${event.type}\n${log.innerText}`;
}

// Keyboard events
document.addEventListener("keydown", getEventType, false); // first
document.addEventListener("keypress", getEventType, false); // second
document.addEventListener("keyup", getEventType, false); // third

// Mouse events
document.addEventListener("mousedown", getEventType, false); // first
document.addEventListener("mouseup", getEventType, false); // second
document.addEventListener("click", getEventType, false); // third
```

### Result

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-type④ |

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

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

See also
--------

* `EventTarget.addEventListener()`
* `EventTarget.removeEventListener()`


Event: cancelBubble property - Web APIs

Event: cancelBubble property
============================

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

 The **`cancelBubble`** property of the `Event`
 interface is deprecated. Use `Event.stopPropagation()` instead.
 Setting its value to `true` before returning from an event handler prevents propagation
 of the event. In later implementations, setting this to `false` does nothing.
 See Browser compatibility for details.

Value
-----

A boolean value. The value `true` means that the event must not be propagated further.

Example
-------

```js
elem.onclick = (event) => {
  // Do cool things here
  event.cancelBubble = true;
};
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-cancelbubble① |

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

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


Event: target property - Web APIs

Event: target property
======================

 The read-only **`target`** property of the
 `Event` interface is a reference to the object onto which the event was
 dispatched. It is different from `Event.currentTarget` when the event
 handler is called during the bubbling or capturing phase of the event.

Value
-----

The associated `EventTarget`.

Example
-------

The `event.target` property can be used in order to implement **event
delegation**.

```js
// Make a list
const ul = document.createElement("ul");
document.body.appendChild(ul);

const li1 = document.createElement("li");
const li2 = document.createElement("li");
ul.appendChild(li1);
ul.appendChild(li2);

function hide(evt) {
  // evt.target refers to the clicked <li> element
  // This is different than evt.currentTarget, which would refer to the parent <ul> in this context
  evt.target.style.visibility = "hidden";
}

// Attach the listener to the list
// It will fire when each <li> is clicked
ul.addEventListener("click", hide, false);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-target③ |

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

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

See also
--------

* Comparison of Event Targets


Event: currentTarget property - Web APIs

Event: currentTarget property
=============================

The **`currentTarget`** read-only property of the `Event` interface identifies the element to which the event handler has been attached.

This will not always be the same as the element on which the event was fired, because the event may have fired on a descendant of the element with the handler, and then bubbled up to the element with the handler. The element on which the event was fired is given by `Event.target`.

Value
-----

An `EventTarget` representing the object to which the current event handler is attached.

Examples
--------

### currentTarget versus target

This example illustrates the difference between `currentTarget` and `target`.

#### HTML

The page has a "parent" `<div>` containing a "child" `<div>`.

```html
<div id="parent">
  Click parent
  <div id="child">Click child</div>
</div>

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

```
button,
div,
pre {
  margin: 0.5rem;
}

div {
  padding: 1rem;
  border: 1px solid black;
}
```

#### JavaScript

The event handler is attached to the parent. It logs the value of `event.currentTarget` and `event.target`.

We also have a "Reset" button that just reloads the example.

```js
const output = document.querySelector("#output");
const parent = document.querySelector("#parent");
parent.addEventListener("click", (event) => {
  const currentTarget = event.currentTarget.getAttribute("id");
  const target = event.target.getAttribute("id");
  output.textContent = `Current target: ${currentTarget}\n`;
  output.textContent += `Target: ${target}`;
});

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

#### Result

If you click inside the child `<div>`, then `target` identifies the child. If you click inside the parent `<div>`, then `target` identifies the parent.

In both cases, `currentTarget` identifies the parent, because that's the element that the handler is attached to.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-currenttarget② |

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

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

See also
--------

* Comparison of Event Targets
* Event bubbling


Event: Event() constructor - Web APIs

Event: Event() constructor
==========================

The **`Event()`** constructor creates a new `Event` object. An event created in this way is called a *synthetic event*, as opposed to an event fired by the browser, and can be dispatched by a script.

Syntax
------

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

### Values

`type`

A string with the name of the event.

`options` Optional

An object with the following properties:

`bubbles` Optional

 A boolean value indicating whether the event bubbles. The default is
 `false`.

`cancelable` Optional

 A boolean value indicating whether the event can be cancelled. The
 default is `false`.

`composed` Optional

 A boolean value indicating whether the event will trigger listeners
 outside of a shadow root (see `Event.composed` for more details). The
 default is `false`.

### Return value

A new `Event` object.

Example
-------

```js
// create a look event that bubbles up and cannot be canceled

const evt = new Event("look", { bubbles: true, cancelable: false });
document.dispatchEvent(evt);

// event can be dispatched from any element, not only the document
myDiv.dispatchEvent(evt);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-event |

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

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

See also
--------

* `Event`
* `EventTarget.dispatchEvent()`
* Creating and triggering events


Event: originalTarget property - Web APIs

Event: originalTarget 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.

The read-only **`originalTarget`** property of the `Event` interface returns the original target of the event before any retargetings. Unlike `Event.explicitOriginalTarget` it can also be native anonymous content.

See also Comparison of Event Targets.

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

*This is a Mozilla-specific property and is not part of any current specification. It is not on track to become a standard.*

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

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


Event: srcElement property - Web APIs

Event: srcElement property
==========================

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

The deprecated **`Event.srcElement`** is an alias for the `Event.target` property. Use `Event.target` instead.

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

| Specification |
| --- |
| DOM Standard # dom-event-srcelement |

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

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

See also
--------

* `Window.event`


Event: stopPropagation() method - Web APIs

Event: stopPropagation() method
===============================

 The **`stopPropagation()`** method of the `Event`
 interface prevents further propagation of the current event in the capturing and
 bubbling phases. It does not, however, prevent any default behaviors from occurring; for
 instance, clicks on links are still processed. If you want to stop those behaviors, see
 the `preventDefault()` method. It also does not
 prevent propagation to other event-handlers of the current element. If you want to stop those,
 see `stopImmediatePropagation()`.

Syntax
------

```js
event.stopPropagation()
```

### Parameters

None.

### Return value

None.

Examples
--------

 See Event Propagation.
 Also see the example at `stopImmediatePropagation()`

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-stoppropagation① |

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

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


Event: timeStamp property - Web APIs

Event: timeStamp property
=========================

The **`timeStamp`** read-only property of the `Event` interface returns the time (in milliseconds) at which the event was created.

Value
-----

 This value is the number of milliseconds elapsed from the beginning of the time origin until the event was created.
 If the global object is `Window`, the time origin is the moment the user clicked on the link, or the script that initiated the loading of the document.
 In a worker, the time origin is the moment of creation of the worker.

The value is a `DOMHighResTimeStamp` accurate to 5 microseconds (0.005 ms), but the precision is reduced to prevent fingerprinting.

Example
-------

### HTML

```html
<p>
  Focus this iframe and press any key to get the current timestamp for the
  keypress event.
</p>
<p>timeStamp: <span id="time">-</span></p>
```

### JavaScript

```js
function getTime(event) {
  const time = document.getElementById("time");
  time.firstChild.nodeValue = event.timeStamp;
}
document.body.addEventListener("keypress", getTime);
```

### Result

Reduced time precision
----------------------

To offer protection against timing attacks and fingerprinting, the precision of `Event.timeStamp` might get rounded depending on browser settings.

In Firefox, the `privacy.reduceTimerPrecision` preference is enabled by default and defaults to 2ms.

```js
// reduced time precision in Firefox (default: 2ms)
event.timeStamp;
// 9934
// 10362
// 11670
// …
```

In Firefox, if you also enable `privacy.resistFingerprinting`, the precision will be 100ms or the value of `privacy.resistFingerprinting.reduceTimerPrecision.microseconds`, whichever is larger.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-timestamp① |

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

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


Event: bubbles property - Web APIs

Event: bubbles property
=======================

The **`bubbles`** read-only property of the `Event` interface indicates whether the event bubbles up through the DOM tree or not.

**Note:** See Event bubbling and capture for more information on bubbling.

Value
-----

A boolean value, which is `true` if the event bubbles up through the DOM tree.

Example
-------

```js
function handleInput(e) {
  // Check whether the event bubbles passes the event along
  if (!e.bubbles) {
    passItOn(e);
  }

  // Already bubbling
  doOutput(e);
}
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-bubbles③ |

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

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

See also
--------

* `stopPropagation()` to prevent further propagation of the current event in the capturing and bubbling phases
* `stopImmediatePropagation()` to not call any further listeners for the same event at the same level in the DOM
* `preventDefault()` to allow propagation to continue but to disallow the browser to perform its default action should no listeners handle the event


Event: isTrusted property - Web APIs

Event: isTrusted property
=========================

 The **`isTrusted`** read-only property of the
 `Event` interface is a boolean value that is `true`
 when the event was generated by a user action, and `false` when the event was
 created or modified by a script or dispatched via
 `EventTarget.dispatchEvent()`.

Value
-----

A boolean value.

Example
-------

```js
if (e.isTrusted) {
  /\* The event is trusted \*/
} else {
  /\* The event is not trusted \*/
}
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-istrusted① |

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

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


Event: eventPhase property - Web APIs

Event: eventPhase property
==========================

 The **`eventPhase`** read-only property of the
 `Event` interface indicates which phase of the event flow is currently
 being evaluated.

Value
-----

 Returns an integer value which specifies the current evaluation phase of the event
 flow. Possible values are:

`Event.NONE (0)`

The event is not being processed at this time.

`Event.CAPTURING_PHASE (1)`

 The event is being propagated through the target's ancestor objects.
 This process starts with the `Window`, then `Document`,
 then the `HTMLHtmlElement`, and so on through the elements
 until the target's parent is reached.
 Event listeners
 registered for capture mode when `EventTarget.addEventListener()` was
 called are triggered during this phase.

`Event.AT_TARGET (2)`

 The event has arrived at
 the event's target.
 Event listeners registered for this phase are called at this time. If
 `Event.bubbles` is `false`, processing
 the event is finished after this phase is complete.

`Event.BUBBLING_PHASE (3)`

 The event is propagating back up through the target's ancestors in reverse order,
 starting with the parent, and eventually reaching the containing `Window`.
 This is known as *bubbling*, and occurs only if `Event.bubbles` is
 `true`. Event listeners registered for this phase are triggered during this process.

Example
-------

### HTML

```html
<h4>Event Propagation Chain</h4>
<ul>
  <li>Click 'd1'</li>
  <li>Analyze event propagation chain</li>
  <li>Click next div and repeat the experience</li>
  <li>Change Capturing mode</li>
  <li>Repeat the experience</li>
</ul>
<input type="checkbox" id="chCapture" />
<label for="chCapture">Use Capturing</label>
<div id="d1">
  d1
  <div id="d2">
    d2
    <div id="d3">
      d3
      <div id="d4">d4</div>
    </div>
  </div>
</div>
<div id="divInfo"></div>
```

### CSS

```css
div {
  margin: 20px;
  padding: 4px;
  border: thin black solid;
}

#divInfo {
  margin: 18px;
  padding: 8px;
  background-color: white;
  font-size: 80%;
}
```

### JavaScript

```js
let clear = false;
let divInfo = null;
let divs = null;
let chCapture = null;

window.onload = () => {
  divInfo = document.getElementById("divInfo");
  divs = document.getElementsByTagName("div");
  chCapture = document.getElementById("chCapture");
  chCapture.onclick = () => {
    removeListeners();
    addListeners();
    clearDivs();
  };
  clearDivs();
  addListeners();
};

function removeListeners() {
  for (const div of divs) {
    if (div.id !== "divInfo") {
      div.removeEventListener("click", onDivClick, true);
      div.removeEventListener("click", onDivClick, false);
    }
  }
}

function addListeners() {
  for (const div of divs) {
    if (div.id !== "divInfo") {
      if (chCapture.checked) {
        div.addEventListener("click", onDivClick, true);
      } else {
        div.addEventListener("click", onDivClick, false);
        div.onmousemove = () => {
          clear = true;
        };
      }
    }
  }
}

function onDivClick(e) {
  if (clear) {
    clearDivs();
    clear = false;
  }
  if (e.eventPhase === 2) {
    e.currentTarget.style.backgroundColor = "red";
  }
  const level =
    ["none", "capturing", "target", "bubbling"][e.eventPhase] ?? "error";
  const para = document.createElement("p");
  para.textContent = `${e.currentTarget.id}; eventPhase: ${level}`;
  divInfo.appendChild(para);
}

function clearDivs() {
  for (let i = 0; i < divs.length; i++) {
    if (divs[i].id !== "divInfo") {
      divs[i].style.backgroundColor = i % 2 !== 0 ? "#f6eedb" : "#cceeff";
    }
  }
  divInfo.textContent = "";
}
```

### Result

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-eventphase③ |

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

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


Event: cancelable property - Web APIs

Event: cancelable property
==========================

 The **`cancelable`** read-only property of the `Event` interface indicates whether the event
 can be canceled, and therefore prevented as if the event never happened.

 If the event is *not* cancelable, then its `cancelable` property will be
 `false` and the event listener cannot stop the event from occurring.

 Most browser-native events that can be canceled are the ones that result from the user
 interacting with the page. Canceling the `click`,
 `wheel`, or
 `beforeunload` events would prevent the user
 from clicking on something, scrolling the page with the mouse wheel, or
 navigating away from the page, respectively.

Synthetic events created by other JavaScript
 code define if they can be canceled when they are created.

 To cancel an event, call the `preventDefault()`
 method on the event. This keeps the implementation from executing the default action
 that is associated with the event.

 Event listeners that handle multiple kinds of events may want to check
 `cancelable` before invoking their `preventDefault()` methods.

Value
-----

 A boolean value, which is `true` if the event can be
 canceled.

Example
-------

 For example, browser vendors are proposing that the `wheel` event can only be canceled the first time the listener is called — any following `wheel` events cannot be
 canceled.

```js
function preventScrollWheel(event) {
  if (typeof event.cancelable !== "boolean" || event.cancelable) {
    // The event can be canceled, so we do so.
    event.preventDefault();
  } else {
    // The event cannot be canceled, so it is not safe
    // to call preventDefault() on it.
    console.warn(`The following event couldn't be canceled:`);
    console.dir(event);
  }
}

document.addEventListener("wheel", preventScrollWheel);
```

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-cancelable② |

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

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


Event: defaultPrevented property - Web APIs

Event: defaultPrevented property
================================

The **`defaultPrevented`** read-only property of the `Event` interface returns a boolean value indicating whether or not the call to `Event.preventDefault()` canceled the event.

Value
-----

A boolean value, where `true` indicates that the default user agent action was prevented, and `false` indicates that it was not.

Example
-------

This example logs attempts to visit links from two `<a>` elements. JavaScript is used to prevent the second link from working.

### HTML

```html
<p><a id="link1" href="#link1">Visit link 1</a></p>
<p><a id="link2" href="#link2">Try to visit link 2</a> (you can't)</p>
<p id="log"></p>
```

### JavaScript

```js
function stopLink(event) {
  event.preventDefault();
}

function logClick(event) {
  const log = document.getElementById("log");

  if (event.target.tagName === "A") {
    log.innerText = event.defaultPrevented
      ? `Sorry, but you cannot visit this link!\n${log.innerText}`
      : `Visiting link…\n${log.innerText}`;
  }
}

const a = document.getElementById("link2");
a.addEventListener("click", stopLink);
document.addEventListener("click", logClick);
```

### Result

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-defaultprevented① |

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

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


Event: composed property - Web APIs

Event: composed property
========================

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

* Learn more
* See full compatibility
* Report feedback

 The read-only **`composed`** property of the
 `Event` interface returns a boolean value which indicates whether
 or not the event will propagate across the shadow DOM boundary into the standard DOM.

 All UA-dispatched UI events are composed (click/touch/mouseover/copy/paste, etc.). Most
 other types of events are not composed, and so will return `false`. For
 example, this includes synthetic events that are created without their
 `composed` option set to `true`.

 Propagation only occurs if the `bubbles` property is also
 `true`. However, capturing only composed events are also handled at host as
 if they were in `AT_TARGET` phase. You can determine the path the event will
 follow through the shadow root to the DOM root by calling
 `composedPath()`.

Value
-----

 A boolean value which is `true` if the event will cross from the
 shadow DOM into the standard DOM after reaching the shadow root. (That is, the first
 node in the shadow DOM in which the event began to propagate.)

 If this value is `false`, the shadow root will be the last node to be
 offered the event.

Examples
--------

 In this example, we define two trivial custom elements, `<open-shadow>` and `<closed-shadow>`,
 both of which take the contents of their text attribute and insert them into the element's
 shadow DOM as the text content of a `<p>` element. The only difference
 between the two is that their shadow roots are attached with their modes set to
 `open` and `closed` respectively.

The two definitions look like this:

```js
customElements.define(
  "open-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({
        mode: "open",
      });

      shadowRoot.appendChild(pElem);
    }
  },
);

customElements.define(
  "closed-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({
        mode: "closed",
      });

      shadowRoot.appendChild(pElem);
    }
  },
);
```

We then insert one of each element into our page:

```html
<open-shadow text="I have an open shadow root"></open-shadow>
<closed-shadow text="I have a closed shadow root"></closed-shadow>
```

Then include a click event listener on the `<html>` element:

```js
document.querySelector("html").addEventListener("click", (e) => {
  console.log(e.composed);
  console.log(e.composedPath());
});
```

 When you click on the `<open-shadow>` element and then the
 `<closed-shadow>` element, you'll notice two things.

1. The `composed` property returns `true` because the
 `click` event is always able to propagate across shadow boundaries.
2. A difference in the value of `composedPath` for the two
 elements.

The `<open-shadow>` element's composed path is this:
```

Array [ p, ShadowRoot, open-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]
```

Whereas the `<closed-shadow>` element's composed path is a follows:
```

Array [ closed-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]
```

 In the second case, the event listeners only propagate as far as the
 `<closed-shadow>` element itself, but not to the nodes inside the
 shadow boundary.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-composed① |

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

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


Event: composedPath() method - Web APIs

Event: composedPath() method
============================

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

* Learn more
* See full compatibility
* Report feedback

 The **`composedPath()`** method of the `Event`
 interface returns the event's path which is an array of the objects on which listeners
 will be invoked. This does not include nodes in shadow trees if the shadow root was
 created with its `ShadowRoot.mode` closed.

Syntax
------

```js
const composed = Event.composedPath()
```

### Parameters

None.

### Return value

 An array of `EventTarget` objects representing the objects on which an
 event listener will be invoked.

Examples
--------

 In the following example, which you can try out at https://mdn.github.io/web-components-examples/composed-composed-path/, we define two trivial custom
 elements, `<open-shadow>` and `<closed-shadow>`, both
 of which take the contents of their text attribute and insert them into the element's
 shadow DOM as the text content of a `<p>` element. The only difference
 between the two is that their shadow roots are attached with their modes set to
 `open` and `closed` respectively.

```js
customElements.define(
  "open-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(pElem);
    }
  },
);

customElements.define(
  "closed-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({ mode: "closed" });
      shadowRoot.appendChild(pElem);
    }
  },
);
```

We then insert one of each element into our page:

```html
<open-shadow text="I have an open shadow root"></open-shadow>
<closed-shadow text="I have a closed shadow root"></closed-shadow>
```

Then include a click event listener on the `<html>` element:

```js
document.querySelector("html").addEventListener("click", (e) => {
  console.log(e.composed);
  console.log(e.composedPath());
});
```

 When you click on the `<open-shadow>` element and then the
 `<closed-shadow>` element, you'll notice two things. First, the
 `composed` property returns `true` because the `click`
 event is always able to propagate across shadow boundaries. Second, you'll notice a
 difference in the value of `composedPath` for the two elements. The
 `<open-shadow>` element's composed path is this:
```

Array [ p, ShadowRoot, open-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]
```

Whereas the `<closed-shadow>` element's composed path is a follows:
```

Array [ closed-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]
```

 In the second case, the event listeners only propagate as far as the
 `<closed-shadow>` element itself, but not to the nodes inside the
 shadow boundary.

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-event-composedpath① |

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

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


Event: returnValue property - Web APIs

Event: returnValue property
===========================

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

 The `Event` property
 **`returnValue`** indicates whether the default action for
 this event has been prevented or not.

 It is set to `true` by
 default, allowing the default action to occur. Setting this property to
 `false` prevents the default action.

**Note:** While `returnValue` has been adopted into the DOM
 standard, it is present primarily to support existing code. Use
 `preventDefault()`, and
 `defaultPrevented` instead of this historical
 property.

Value
-----

 A boolean value which is `true` if the event has not been
 canceled; otherwise, if the event has been canceled or the default has been prevented,
 the value is `false`.

 The value of `returnValue` is the opposite of the value returned by
 `defaultPrevented`.

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

| Specification |
| --- |
| DOM Standard # dom-event-returnvalue |

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

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

See also
--------

* `HTMLDialogElement.returnValue`: the return value for the `<dialog>`.


WindowSharedStorage: run() method - Web APIs

WindowSharedStorage: run() method
=================================

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

 The **`run()`** method of the
 `WindowSharedStorage` interface executes a run operation that is registered in a module added to the current origin's `SharedStorageWorklet`.

**Note:** The Run output gate is intended as a generic way to process some shared storage data.

Syntax
------

```js
run(name)
run(name, options)
```

### Parameters

`name`

A string representing the registered operation's name within the shared storage worklet module. It must match the name given to the operation when it is registered with `SharedStorageWorkletGlobalScope.register()`.

`options` Optional

An options object that can contain the following properties:

`data` Optional

An object representing any data required for executing the operation.

`keepAlive` Optional

A boolean value. If set to `true`, the `SharedStorageWorkletGlobalScope` of the associated worklet is kept alive, and the operation can be run again. Therefore, you need to set `keepAlive` to `true` for each operation that is not intended to be the last one. The default value, `false`, means that the `SharedStorageWorkletGlobalScope` is terminated after the operation is run and cannot be run again.

### Return value

A `Promise` that fulfills with `undefined`.

### Exceptions

`TypeError`

Thrown if:

* The worklet module has not yet been added with `addModule()`.
* Shared storage is disabled (for example via a browser setting).
* The calling site does not have the Shared Storage API included in a successful privacy sandbox enrollment process.

Examples
--------

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

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

measureUniqueReach();
```

See Unique reach measurement for a full explanation of this example. See Shared Storage API for more examples.

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

| Specification |
| --- |
| Shared Storage API # dom-windowsharedstorage-run |

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

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

See also
--------

* Shared Storage API