IDBCursor.key - Web API 接口参考

IDBCursor.key
=============

**key**是只读属性，返回在游标中的位置。如果游标在范围之外，这个值会被置为 undefined。游标的 key 可以是任何数据类型。

**备注：** 此特性在 Web Worker 中可用

语法
--
```

var key = cursor.key;
```

### 值

任意类型

示例
--

在该示例中，我们创建一个事务，检索一个存储对象，然后使用游标遍历所有存储在 object store 中的记录。遍历的过程中，我们把类似（相簿标题，这是我们的键 key），游标的 key 打印出来。

我们可以不根据游标的 key 来选取数据；我们可以抓取所有。还要注意，在循环的每个迭代中，你可以使用 cursor.value.foo 从当前记录下获取数据。完整示例，请看IDBCursor example (view example live.)
```

function displayData() {
  var transaction = db.transaction(['rushAlbumList'], "readonly");
  var objectStore = transaction.objectStore('rushAlbumList');

  objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if(cursor) {
      var listItem = document.createElement('li');
      listItem.innerHTML = cursor.value.albumTitle + ', ' + cursor.value.year;
      list.appendChild(listItem);

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

规范
--

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

浏览器兼容性
------

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

相关链接
----

* 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 example live.)


MediaStreamTrack.getConstraints() - Web API 接口参考

MediaStreamTrack.getConstraints()
=================================

`MediaStreamTrack` 接口的 **`getConstraints()`** 方法接口返回 `MediaTrackConstraints` 包含集使用现有呼叫最近的轨道建立约束来 `applyConstraints()` (en-US)。这些约束指示网站或应用程序指定的值和值范围对于包含的可约束属性是必需的或可接受的。

约束条件可以用来确保媒体符合你喜欢的某些指导方针。例如，你可能更喜欢高清视频，但要求帧率略低，以帮助保持足够低的数据速率而不会使网络负担过重。约束还可以指定理想和/或可接受的尺寸或尺寸范围。有关如何使用可约束属性的详细信息， (en-US)请参阅能力，约束和设置 (en-US)。

句法
--
```

var constraints = MediaStreamTrack.getConstraints();
```

### 参数

没有。

### 返回值

指示使用`applyConstraints()` (en-US)最近设置的网站或应用程序的可约束属性的`MediaTrackConstraints`对象。返回对象中的属性按照与设置时相同的顺序列出，并且未包含未由网站或应用专门设置的属性。

**备注：** 返回的一组约束条件不一定描述媒体的实际状态; 如果任何约束无法满足，它们仍然包含在网站代码最初设置的返回对象中。要获得所有可约束属性的当前活动设置，你应该调用`getSettings()` (en-US)。

例
-

本示例获取当前轨道约束，设置`facingMode` (en-US)，并应用更新的约束。

```js
function switchCameras(track，camera){
  let constraints = track.getConstraints();
  constraints.facingMode = camera;
  track.applyConstraints(约束);
}
```

规范
--

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-getconstraints |

浏览器兼容性
------

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


MediaStreamTrack.stop() - Web API 接口参考

MediaStreamTrack.stop()
=======================

\*\*`MediaStreamTrack.stop()`\*\*方法停止跟踪。

语法
--
```

track.stop()
```

说明
--

调用`stop()`告诉user agent ，`MediaStreamTrack`不再需要轨道的来源，无论该来源是什么，包括文件，网络流，本地摄像机或麦克风。由于多个音轨可能使用同一音源（例如，如果两个选项卡使用设备的麦克风），则音源本身并不一定会立即停止。而是从轨道取消关联，并且停止跟踪对象。一旦没有媒体轨道正在使用源，则实际上可能会完全停止该源。

调用`stop()`之后，`readyState`属性立即设置为`ended`。

示例
--

### 停止视频流

在此示例中，我们看到一个函数，该函数通过在给定`<video>`的每个轨道上调用`stop()`来停止流式视频。

```js
function stopStreamedVideo(videoElem) {
  const stream = videoElem.srcObject;
  const tracks = stream.getTracks();

  tracks.forEach(function (track) {
    track.stop();
  });

  videoElem.srcObject = null;
}
```

这是通过从其`srcObject` 属性获得视频元素的流来实现的。然后，通过调用其`getTracks()`方法来获取流的轨道列表。从那里开始，剩下要做的就是使用`forEach()`遍历轨道列表并调用每个轨道的`stop()`方法。

最后，将`srcObject`设置为`null`以切断与`MediaStream` 对象的链接，以便将其释放。

Finally, `srcObject` is set to `null` to sever the link to the `MediaStream` object so it can be released.

规范
--

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-stop |

浏览器兼容性
------

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

看看别的
----

* `MediaStreamTrack`，它所属的接口。
* `MediaStreamTrack.readyState`
* `ended`


MediaStreamTrack.readyState - Web API 接口参考

MediaStreamTrack.readyState
===========================

\*\*`MediaStreamTrack.readyState`\*\*只读属性返回一个枚举的值，该值给出了轨道的状态。

语法
--
```

const state = track.readyState
```

### 值

它采用以下值之一：

* `"live"`表示输入已连接，并尽最大努力提供实时数据。在这种情况下，可以使用`MediaStreamTrack.enabled` (en-US)属性打开或关闭数据输出。
* `"ended"`表示输入不再提供任何数据，也永远不会提供新数据。
规范
--

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-readystate |

浏览器兼容性
------

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

看看别的
----

* Media Stream API
* WebRTC
* `MediaStreamTrack.onended` (en-US)


MediaStreamTrack.getCapabilities() - Web API 接口参考

MediaStreamTrack.getCapabilities()
==================================

`MediaStreamTrack` 接口的 **`getCapabilities()`** 方法返回一个 `MediaTrackCapabilities` 对象，此对象表示每个可调节属性的值或者范围，该特性依赖于平台和user agent.

一旦你知道了浏览器的功能，你的脚本可以通过调用 `applyConstraints()` (en-US) 来请求配置为匹配理想或可接受的设置。参考功能、约束和设置 (en-US)以了解受限制属性的具体细节。

语法
--
```

var capabilities = MediaStreamTrack.getCapabilities();
```

### 参数

没有参数。

### 返回值

A `MediaTrackCapabilities` object which specifies the value or range of values which are supported for each of the user agent's supported constrainable properties.

规范
--

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-getcapabilities |

浏览器兼容性
------

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


StyleSheet.disabled - Web API 接口参考

StyleSheet.disabled
===================

`StyleSheet`接口的 **`disabled`** 属性用于决定样式表是否被禁用于文档。样式表被禁用可能由于这个属性被手动设置为 true，也可能是因为样式表是未激活的alternative style sheet。注意 `disabled == false` 并不保证样式表一定生效（例如它可能被移除出文档）。

语法
--
```

bool = stylesheet.disabled
```

例子
--
```

// 如果样式表被禁用
if (stylesheet.disabled) {
   // 添加行内样式
}
```

规范
--

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-stylesheet-disabled |

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

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


StyleSheet.title - Web API 接口参考

StyleSheet.title
================

概述
--

The **`title`** property of the `StyleSheet` interface returns the advisory title of the current style sheet.

The title is often specified in the `ownerNode` (en-US).

注意
--

The title is often specified in the `ownerNode` (en-US).

Specification
-------------

* title
浏览器兼容性
------

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


StyleSheet.media - Web API 接口参考

StyleSheet.media
================

概述
--

**media** specifies the intended destination medium for style information.

语法
--
```

medium = stylesheet.media
stylesheet.media =medium
```

参数
--

* `medium` is a string describing a single medium or a comma-separated list.
示例
--
```

<link rel="StyleSheet" href="document.css" type="text/css" media="screen" />
```

注意
--

The default value for media is "screen."

Specification
-------------

DOM Level 2 Styles - STYLESHEET


href - Web API 接口参考

href
====

### 概述

返回当前样式表文件的 URI 地址。

### 语法
```

uri = stylesheet.href
```

### 参数

* `uri` 为一个字符串，包含了样式表文件的 URI 地址。
### 例子
```

 // 在本机环境下
 <html>
  <head>
   <link rel="StyleSheet" href="example.css" type="text/css" />
   <script>
    function sref() {
     alert(document.styleSheets[0].href);
    }
   </script>
  </head>
  <body>
   <div class="thunder">Thunder</div>
   <button onclick="sref()">ss</button>
  </body>
 </html>
// 弹出 "file:////C:/Windows/Desktop/example.css
```

### 备注

如果该样式表是一个外链样式表文件，则它的 href 属性值为样式表文件的 URI. 但如果该样式表是一个内联样式表，则它的 href 属性值为`null`.

该属性在 Firefox, Opera, Google Chrome, Safari 中为只读属性，在 Internet Explorer 中可读可写。

### 规范

stylesheet.href


使用 MediaStream 的录制 API - Web API 接口参考

使用 MediaStream 的录制 API
======================

媒体流 (音/视频) 录制 API让记录音频流或视频流信息更加容易。当使用navigator.mediaDevices.getUserMedia()" (en-US)时，它提供了一种简单的方式从用户的输入设备中记录信息，并且可以马上在 web apps 中查看记录的信息。音/视频信息都可以被录制，可以分开也可以一块儿。本文针对于提供一个基础引导去让大家了解提供了这个 API 的 MediaRecorder 的界面。

示例应用：Web 录音机
------------

![An image of the Web dictaphone sample app - a sine wave sound visualization, then record and stop buttons, then an audio jukebox of recorded tracks that can be played back.](/zh-CN/docs/Web/API/MediaStream_Recording_API/Using_the_MediaStream_Recording_API/web-dictaphone.png)

为了验证 MediaRecorder API 的基础用法，我们做了一个基于 web 的录音机。它允许你录制音频片段并播放它。通过使用这个 web 音频 API，它甚至给你提供了一个设备音频输入信息的可视化波浪图。我们在本文中专注于录制和回放功能的实现。

你可以看到实例演示或是 Github 上的源码（也可以点此直接下载）。

CSS goodies
-----------

在这个 app 应用中的网页是相当简单的，所以我们不会在这里大费周章；但有几个有点意思的 CSS 样式还是有必要提一下，所以接下来我们会讨论一下。如果你对 CSS 没有半毛钱兴趣并且想对 JavaSdcript 单刀直入，请跳转到下面的应用基础设置章节。

### 保持主界面对显示区域的约束，用 calc() 来忽略设备的尺寸

calc() 函数是 CSS3 中出现的非常实用的功能之一，虽然现在的用处和这个名称看上去关系不大，但是你很快就会觉得“WC，这个功能为什么我们之前没有？为什么之前 CSS2 的布局会这么蛋疼？”它允许你计算一个 CSS 单元的计算值，在这个过程中混合不同的单元。

例如，在 Web 录音机中，我们有主要的 UI 区域，垂直堆叠。我们先给出前两块地方（头部和控制件）的固定高度：

```css
header {
  height: 70px;
}

.main-controls {
  padding-bottom: 0.7rem;
  height: 170px;
}
```

然而，我们希望使第三块区域（其中包含你可以回放的记录样例）占用任何空间，而不用担心设备的高度。Flexbox 流动样式可能是这里的答案，但是对于这样一个简单的布局来说有点过头了。相反，问题是通过使第三个容器的高度等于父高度的 100%，再减去另两个的高度和填充来解决的。

```css
.sound-clips {
  box-shadow: inset 0 3px 4px rgba(0, 0, 0, 0.7);
  background-color: rgba(0, 0, 0, 0.1);
  height: calc(100% - 240px - 0.7rem);
  overflow: scroll;
}
```

**备注：** 现在的浏览器对calc()有着良好的支持，即使是像 IE9 那样的浏览器也可以。

### 用于显示/隐藏的复选框

虽然目前已经做的不错了，但是我们认为我们会提到一个复选框 hack 做法，它滥用了一个事实，你可以点击复选框的label 标签来切换选中/未选中。在 web 录音机中，通过点击屏幕右上角的问号图标来显示/隐藏信息屏幕。首先，在得到<label>标签之前我们得先设计它的样式，通过设置足够的 Z-index 堆叠次序来确保它总是坐落于其他元素之上，所以它应该是可点击的：

```css
label {
  font-family: "NotoColorEmoji";
  font-size: 3rem;
  position: absolute;
  top: 2px;
  right: 3px;
  z-index: 5;
  cursor: pointer;
}
```

然后，我们隐藏实际的复选框，因为我们不希望它在我们的 UI 上乱七八糟：

```css
input[type="checkbox"] {
  position: absolute;
  top: -100px;
}
```

接下来，我们将设计信息显示区域（包括在<aside>元素中），给它固定的位置，使它不出现在布局流程中去影响主要的 UI 三个户，将它转换为默认的位置，并使它平滑显示/隐藏：

```css
aside {
  position: fixed;
  top: 0;
  left: 0;
  text-shadow: 1px 1px 1px black;
  width: 100%;
  height: 100%;
  transform: translateX(100%);
  transition: 0.6s all;
  background-color: #999;
  background-image: linear-gradient(
    to top right,
    rgba(0, 0, 0, 0),
    rgba(0, 0, 0, 0.5)
  );
}
```

最后，我们编写一个规则，当选中复选框（当我们点击/聚焦标签）时，相邻的<aside >元素将使它的水平平移值发生变化，并平滑地转换成视图：

```css
input[type="checkbox"]:checked ~ aside {
  transform: translateX(0);
}
```

应用基础设置
------

我们使用 getUserMedia() 来捕获我们想要的媒体流。我们使用 MediaRecorder API 来记录信息流，并将每个记录的片段输出到生成的<audio>元素的源中，以便可以回放。

我们将声明记录和停止按钮变量，<article>元素将包含生成的音频播放器：

```js
var record = document.querySelector(".record");
var stop = document.querySelector(".stop");
var soundClips = document.querySelector(".sound-clips");
```

最后，在本节中，我们建立了基本的 getUserMedia 结构：

```js
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  console.log("getUserMedia supported.");
  navigator.mediaDevices
    .getUserMedia(
      // constraints - only audio needed for this app
      {
        audio: true,
      },
    )

    // Success callback
    .then(function (stream) {})

    // Error callback
    .catch(function (err) {
      console.log("The following getUserMedia error occured: " + err);
    });
} else {
  console.log("getUserMedia not supported on your browser!");
}
```

整个事件被封装在一个测试中，该测试在运行其他操作之前检查是否支持`getUserMedia`。接下来，我们调用`getUserMedia`，并在其内部定义：

* 限制：只有音频才能被捕获到我们的录音机
* 成功回调：一旦成功完成`getUserMedia`调用，此代码就会运行。
* 错误/失败回调：如果`getUserMedia`调用由于任何原因而失败，则代码将运行。

**备注：** 下面的所有代码都放在`getUserMedia`成功回调中。

捕获媒体流
-----

一旦`getUserMedia`成功创建了媒体流，你可以使用 MediaRecorder() 构造函数创建一个新的媒体记录器实例，并直接传递该媒体流流。这是使用 MediaRecorder API 的入口点。现在，可以使用浏览器的默认编码格式将流捕获到Blob。

```js
var mediaRecorder = new MediaRecorder(stream);
```

为了能够方便的控制音频的录制，`MediaRecorder`的实例提供了一系列有用的方法和事件，在 Web Dictaphone 这个简单的项目中我们只需使用其中的 2 个方法和一些事件。首先，为了能在点击 Record 按钮的时候开始录音，需要调用`MediaRecorder.start()` (en-US)：

```js
record.onclick = function () {
  mediaRecorder.start();
  console.log(mediaRecorder.state);
  console.log("recorder started");
  record.style.background = "red";
  record.style.color = "black";
};
```

当`MediaRecorder`正在记录时，调用`MediaRecorder.state` (en-US)会返回"recording"。

为了收集录制的数据，我们需要监听`mediaRecorder.ondataavailable`事件：

```js
var chunks = [];

mediaRecorder.ondataavailable = function (e) {
  chunks.push(e.data);
};
```

浏览器会在需要的时候触发这个事件，我们也可以通过为`MediaRecorder.start()` (en-US)传递一个时间（毫秒）来周期性的触发这个事件或者调用`MediaRecorder.requestData()` (en-US)来直接触发。

最后在点击 Stop 按钮时我们调用`MediaRecorder.stop()` (en-US)方法结束录制，录制所产生的`Blob`数据会在后面使用。

```js
stop.onclick = function () {
  mediaRecorder.stop();
  console.log(mediaRecorder.state);
  console.log("recorder stopped");
  record.style.background = "";
  record.style.color = "";
};
```

注意，当媒体流结束时会导致录音终止。例如歌曲播放结束，或者用户停止共享他们的麦克风。

抓取并使用 blob 数据
-------------

在停止录制后，实例的 state 属性会返回"inactive"，stop 事件也被触发。我们需要监听这个事件去处理我们收到的所有录制数据：

```js
mediaRecorder.onstop = function (e) {
  console.log("recorder stopped");

  var clipName = prompt("Enter a name for your sound clip");

  var clipContainer = document.createElement("article");
  var clipLabel = document.createElement("p");
  var audio = document.createElement("audio");
  var deleteButton = document.createElement("button");

  clipContainer.classList.add("clip");
  audio.setAttribute("controls", "");
  deleteButton.innerHTML = "Delete";
  clipLabel.innerHTML = clipName;

  clipContainer.appendChild(audio);
  clipContainer.appendChild(clipLabel);
  clipContainer.appendChild(deleteButton);
  soundClips.appendChild(clipContainer);

  var blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
  chunks = [];
  var audioURL = window.URL.createObjectURL(blob);
  audio.src = audioURL;

  deleteButton.onclick = function (e) {
    var evtTgt = e.target;
    evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
  };
};
```

我们来看一下上面的代码干了什么：

首先，用一个弹窗来让用户可以为录音提供一个名称。

接下来，我们创建一个如下所示的 HTML 结构，将其插入到我的剪辑容器中，这是一个`<article>`元素。

```html
<article class="clip">
  <audio controls></audio>
  <p>your clip name</p>
  <button>Delete</button>
</article>
```

之后，我们从录制的音频块中创建组合`Blob`，并使用 window.URL.createObjectURL(blob) 创建指向它的对象 URL。然后我们将 `<audio>`元素的`src`属性的值设置为对象 URL，以便在音频播放器上按下播放按钮时，它会播放音频。

最后，我们监听删除按钮的 onclick 事件，以便能够删除整个剪辑 HTML 结构。

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

| Specification |
| --- |
| MediaStream Recording # mediarecorder-api |

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

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

See also
--------

* MediaRecorder API (en-US) landing page
* `Navigator.getUserMedia()`
* MediaRecorder API now supported by 65% of your website users


AbortController.signal - Web API 接口参考

AbortController.signal
======================

`AbortController` 接口的只读属性 **`signal`** 返回一个 `AbortSignal` 实例对象，该对象可以根据需要处理 DOM 请求通信，既可以建立通信，也可以终止通信。

值
-

一个 `AbortSignal` 实例对象。

示例
--

在下面的这段代码中，我们将通过 Fetch API 来下载一段视频。

首先通过 `AbortController()` 构造函数来创建一个 controller 实例，然后通过 `AbortController.signal` 属性获取到它的关联对象 `AbortSignal` 的引用。

当 fetch 请求初始化时，我们将 `AbortSignal` 作为一个选项传递进入请求的选项对象中（下面的 `{signal}`）。这将 signal 和 controller 与 fetch 请求相关联，并且允许我们通过调用 `AbortController.abort()` 去中止它，如下面的第二个事件监听器。

```js
const controller = new AbortController();
const signal = controller.signal;

const url = "video.mp4";
const downloadBtn = document.querySelector(".download");
const abortBtn = document.querySelector(".abort");

downloadBtn.addEventListener("click", fetchVideo);

abortBtn.addEventListener("click", () => {
  controller.abort();
  console.log("Download aborted");
});

function fetchVideo() {
  fetch(url, { signal })
    .then((response) => {
      console.log("Download complete", response);
    })
    .catch((err) => {
      console.error(`Download error: ${err.message}`);
    });
}
```

**备注：** 当 `abort()` 被调用，`fetch()` promise 将会抛出一个 `AbortError`.

你可以在 GitHub 上找到完整的可以运行的示例；你还可以看它的在线演示。

规范
--

| Specification |
| --- |
| DOM Standard # ref-for-dom-abortcontroller-signal② |

浏览器兼容性
------

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

参见
--

* Fetch API


AbortController.abort() - Web API 接口参考

AbortController.abort()
=======================

`AbortController` 接口的 **`abort()`** 方法会在 DOM 请求完成之前中止它。它能够中止 fetch 请求、各种响应主体或者流的消耗。

语法
--

```js
abort()
abort(reason)
```

### 参数

`reason` 可选

操作中止的原因，可以是各种 JavaScript 值。如果没有指定，则将原因设置为“AbortError”`DOMException`。

### 返回值

无（`undefined`）。

示例
--

以下片段中，我们将使用 Fetch API 下载一个视频。

我们首先使用 `AbortController()` 构造函数创建一个 controller，然后使用 `AbortController.signal` 属性获取到它关联的 `AbortSignal` 对象的引用。

当 fetch 请求初始化时，我们将 `AbortSignal` 作为一个选项传递进入请求的选项对象中（下面的 `{signal}`）。这将 signal 和 controller 与 fetch 请求相关联，并且允许我们通过调用 `AbortController.abort()` 去中止它，如下面的第二个事件监听器。

```js
const controller = new AbortController();
const signal = controller.signal;

const url = "video.mp4";
const downloadBtn = document.querySelector(".download");
const abortBtn = document.querySelector(".abort");

downloadBtn.addEventListener("click", fetchVideo);

abortBtn.addEventListener("click", () => {
  controller.abort();
  console.log("Download aborted");
});

function fetchVideo() {
  fetch(url, { signal })
    .then((response) => {
      console.log("Download complete", response);
    })
    .catch((err) => {
      console.error(`Download error: ${err.message}`);
    });
}
```

**备注：** 当 `abort()` 被调用时，`fetch()` promise 将会抛出 `DOMException` 类型的 `Error`（名称为 `AbortError`）。

你可以在 github 上找到完整的工作示例；你还可以看它的在线演示。

规范
--

| Specification |
| --- |
| DOM Standard # ref-for-dom-abortcontroller-abortcontroller① |

浏览器兼容性
------

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

参见
--

* Fetch API


AbortController.AbortController() - Web API 接口参考

AbortController.AbortController()
=================================

**`AbortController()`** 构造函数创建了一个新的 `AbortController` 实例。

语法
--

```js
new AbortController()
```

### 参数

无。

示例
--

在下面的这段代码中，我们将通过 Fetch API 来下载一段视频。

首先通过 `AbortController()` 构造函数来创建一个 controller 实例，然后通过 `AbortController.signal` 属性获取到它的关联对象 `AbortSignal` 的引用。

当 fetch 请求初始化时，我们将 `AbortSignal` 作为一个选项传递进入请求的选项对象中（下面的 `{signal}`）。这将 signal 和 controller 与 fetch 请求相关联，并且允许我们通过调用 `AbortController.abort()` 去中止它，如下面的第二个事件监听器。

```js
const controller = new AbortController();
const signal = controller.signal;

const url = "video.mp4";
const downloadBtn = document.querySelector(".download");
const abortBtn = document.querySelector(".abort");

downloadBtn.addEventListener("click", fetchVideo);

abortBtn.addEventListener("click", () => {
  controller.abort();
  console.log("Download aborted");
});

function fetchVideo() {
  fetch(url, { signal })
    .then((response) => {
      console.log("Download complete", response);
    })
    .catch((err) => {
      console.error(`Download error: ${err.message}`);
    });
}
```

**备注：** 当 `abort()` 被调用，`fetch()` promise 将会抛出 `AbortError`。

你可以在 GitHub 上找到一个完整的使用示例——参见 abort-api（也可以看在线演示）。

规范
--

| Specification |
| --- |
| DOM Standard # ref-for-dom-abortcontroller-abortcontroller① |

浏览器兼容性
------

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

参见
--

* Fetch API


IDBObjectStore.indexNames - Web API 接口参考

IDBObjectStore.indexNames
=========================

`IDBObjectStore` 的只读属性 **`indexNames`** 返回此对象存储中对象的 indexes 名称（name）列表。

**备注：** 此特性在 Web Worker 中可用

Syntax
------
```

var myindexNames = objectStore.indexNames;
```

### Value

一个 `DOMStringList`.

Example
-------

在下面的代码片段中，我们在数据库上打开一个读/写事务并使用 `add()` 向对象存储添加一些数据。创建对象存储后，我们将打印 `objectStore.indexNames` 到控制台。有关完整的工作示例，请参阅我们的 待办事项通知应用程序 ( 实时查看示例 )

```js
// 让我们来打开我们的数据库
var DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onsuccess = function (event) {
  note.innerHTML += "<li>Database initialised.</li>";

  // 将打开数据库的结果存储在 db 变量中
  // 下面经常用到这个
  db = this.result;

  // 运行 addData() 函数将数据添加到数据库
  addData();
};

function addData() {
  // 创建一个新对象以准备插入到 IDB 中
  var newItem = [
    {
      taskTitle: "Walk dog",
      hours: 19,
      minutes: 30,
      day: 24,
      month: "December",
      year: 2013,
      notified: "no",
    },
  ];

  // 打开读/写数据库事务，准备添加数据
  var transaction = db.transaction(["toDoList"], "readwrite");

  // 当所有事情都完成时，报告事务完成的成功情况
  transaction.oncomplete = function (event) {
    note.innerHTML += "<li>Transaction completed.</li>";
  };

  transaction.onerror = function (event) {
    note.innerHTML +=
      "<li>Transaction not opened due to error. Duplicate items not allowed.</li>";
  };

  // 在事务上创建对象存储
  var objectStore = transaction.objectStore("toDoList");
  console.log(objectStore.indexNames);

  // 请求将 newItem 对象 添加到对象存储区
  var objectStoreRequest = objectStore.add(newItem[0]);

  objectStoreRequest.onsuccess = function (event) {
    // 报告我们请求的成功
    note.innerHTML += "<li>Request successful.</li>";
  };
}
```

规范
--

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-indexnames① |

浏览器兼容性
------

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

查看其他内容
------

* 使用 IndexedDB
* 启动事务 : `IDBDatabase`
* 使用事务 : `IDBTransaction`
* 设置键的范围 : `IDBKeyRange`
* 检索和更改数据 : `IDBObjectStore`
* 使用游标 : `IDBCursor`
* 参考示例 : To-do Notifications (view example live.)


IDBObjectStore.put() - Web API 接口参考

IDBObjectStore.put()
====================

`IDBObjectStore` 接口的 **`put()`** 方法更新一条给定的数据库记录，如果给出的值不存在，则插入一个新的记录

它返回一个 `IDBRequest` 对象，并且在一个单独的线程 ,创建一个值的 structured clone ,并且把它的值储存在对象仓库 (object store) 中。当事务的模式是`readwrite 时，`这个方法用来添加新的记录，或者更新一条对象仓库 (object store) 中已存在的记录 . 如果记录被成功储存，then a success event is fired on the returned request object with the `result` set to the key for the stored record, and the `transaction` set to the transaction in which this object store is opened.

put 方法是一个插入或更新对象仓库的方法。参考仅用于插入的方法 `IDBObjectStore.add` 方法。

谨记，如果你有一条 `IDBCursor` (en-US) 记录想要更新，使用`IDBCursor.update()` (en-US) 方法更新，比 `IDBObjectStore.put()` 方法更合适。这样做可以清楚地表明将更新现有记录，而不是插入新记录。

**备注：** 此特性在 Web Worker 中可用

语法
--
```

var request = objectStore.put(item);
var request = objectStore.put(item, key);
```

### 参数

item

你想要更新 (或插入) 的记录。

key 可选

你想要更新记录的主键 (e.g. from `IDBCursor.primaryKey` (en-US)). This is only needed for object stores that have an `autoIncrement` primary key, therefore the key is not in a field on the record object. In such cases, calling `put(item)` will always insert a new record, because it doesn't know what existing record you might want to modify.

### 返回值

一个 `IDBRequest` 对象 ,在该对象上触发与此操作相关的后续事件。

### 异常

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

| Exception | Description |
| --- | --- |
| `ReadOnlyError` |
 The transaction associated with this operation is in read-only
 mode (en-US).
  |
| `TransactionInactiveError` | This `IDBObjectStore`'s transaction is inactive. |
| `DataError` | Any of the following conditions apply:* The object store uses in-line keys or has a key generator, and a key
 parameter was provided.
* The object store uses out-of-line keys and has no key generator, and
 no key parameter was provided.
* The object store uses in-line keys but no key generator, and the
 object store's key path does not yield a valid key.
* The key parameter was provided but does not contain a valid key.
 |
| `InvalidStateError` |
 The `IDBObjectStore` has been deleted or
 removed.
  |
| `DataCloneError` |
 The data being stored could not be cloned by the internal structured
 cloning algorithm. |

参数
--

value

被储存的值。

key

识别记录的键。如果没有声明，那么记录键值将为空。如果对象仓库有一个键生成器 (e.g. autoincrement) ,必须传入 key 来更新对象。

Example
-------

The following example requests a given record title; when that request is successful the `onsuccess` function gets the associated record from the `IDBObjectStore` (made available as `objectStoreTitleRequest.result`), updates one property of the record, and then puts the updated record back into the object store in another request with `put()`. For a full working example, see our To-do Notifications app (view example live.)

```js
var title = "Walk dog";

// Open up a transaction as usual
var objectStore = db
  .transaction(["toDoList"], "readwrite")
  .objectStore("toDoList");

// Get the to-do list object that has this title as it's title
var objectStoreTitleRequest = objectStore.get(title);

objectStoreTitleRequest.onsuccess = function () {
  // Grab the data object returned as the result
  var data = objectStoreTitleRequest.result;

  // Update the notified value in the object to "yes"
  data.notified = "yes";

  // Create another request that inserts the item back into the database
  var updateTitleRequest = objectStore.put(data);

  // Log the transaction that originated this request
  console.log(
    "The transaction that originated this request is " +
      updateTitleRequest.transaction,
  );

  // When this new request succeeds, run the displayData() function again to update the display
  updateTitleRequest.onsuccess = function () {
    displayData();
  };
};
```

Specification
-------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-put① |

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 example live.)


IDBObjectStore.keyPath - Web API 接口参考

IDBObjectStore.keyPath
======================

`IDBObjectStore`的只读属性 keyPath 接口返回当前 objectStore 的key path (en-US)。

什么是 keyPath 呢？在 indexedDB 中，一条记录就是一个 object，object 里面有一个属性作为这条记录的主要依据用来进行查询，而这个属性的属性名就是 keyPath，属性值就是 key。在用 indexedDB 的 get 方法时，提供 key，而不需要指定 keyPath，因为 get 方法把参数作为这个最主要的属性的值，在数据库中进行查询。（译者注）

如果该属性值为 null，应用中必须在每一次进行修改性质的操作时提供一个 key。

add、put 方法都可以传第二个参数，当你当前的 objectStore 的 autoIncrement 为 true 时，你一般不会设置 keyPath，如果这个时候你在 put 的时候不提供第二个参数，indexedDB 就不知道要更新哪一条记录了。（译者注）

**备注：** 此特性在 Web Worker 中可用

句法
--
```

var mykeyPath = objectStore.keyPath;
```

### Value

任何类型。

例子
--

在下面代码片段中，我们在数据库里打开了一个可读写的事务（transaction），并且用`add()`向一个 objectStore 中添加了一些数据。在 objectStore 被创建之后，我们在 console 中打印了 objectStore.keyPath 的值。想查看完整的例子，请查看我们的To-do Notifications应用（查看在线例子）。

```js
// Let us open our database
var DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onsuccess = function (event) {
  note.innerHTML += "<li>Database initialised.</li>";

  // store the result of opening the database in the db variable.
  // This is used a lot below
  db = DBOpenRequest.result;

  // Run the addData() function to add the data to the database
  addData();
};

function addData() {
  // Create a new object ready to insert into the IDB
  var newItem = [
    {
      taskTitle: "Walk dog",
      hours: 19,
      minutes: 30,
      day: 24,
      month: "December",
      year: 2013,
      notified: "no",
    },
  ];

  // open a read/write db transaction, ready for adding the data
  var transaction = db.transaction(["toDoList"], "readwrite");

  // report on the success of the transaction completing, when everything is done
  transaction.oncomplete = function (event) {
    note.innerHTML += "<li>Transaction completed.</li>";
  };

  transaction.onerror = function (event) {
    note.innerHTML +=
      "<li>Transaction not opened due to error. Duplicate items not allowed.</li>";
  };

  // create an object store on the transaction
  var objectStore = transaction.objectStore("toDoList");
  console.log(objectStore.keyPath);

  // Make a request to add our newItem object to the object store
  var objectStoreRequest = objectStore.add(newItem[0]);

  objectStoreRequest.onsuccess = function (event) {
    // report the success of our request
    note.innerHTML += "<li>Request successful.</li>";
  };
}
```

规范
--

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-keypath① |

浏览器兼容性
------

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

相关内容
----

* 使用 IndexedDB
* 开始学习事务 transactions: `IDBDatabase`
* 使用事务 transactions: `IDBTransaction`
* 值域 range 的使用：`IDBKeyRange`
* 检索、修改：`IDBObjectStore`
* 使用游标：`IDBCursor`
* 相关例子：To-do Notifications (view example live.)


IDBObjectStore.autoIncrement - Web API 接口参考

IDBObjectStore.autoIncrement
============================

`IDBObjectStore`的只读属性 **`autoIncrement`** 接口返回当前 objectStore 的自增标记值（true 或 false）。

什么是自增呢？熟悉 SQL 的朋友应该知道，SQL 数据里面的字段可以设置自增，当一条记录被插入时，不必传入该字段，新记录的该字段值会在前面一条记录该字段值的基础上加 1.而 indexedDB 里面的 autoIncrement 的同样的意义。（译者注）

注意：每个 objectStore 的 auto increment 计数器是分开独立的。

**备注：** 此特性在 Web Worker 中可用

句法
--
```

var myAutoIncrement = objectStore.autoIncrement;
```

### Value

`Boolean` (en-US):

| 值 | 含义 |
| --- | --- |
| `true` | 当前 objectStore 会自增 |
| `false` | 当前 objectStore 不会自增 |

例子
--

在下面代码片段中，我们在数据库里打开了一个可读写的事务（transaction），并且用`add()`向一个 objectStore 中添加了一些数据。在 objectStore 被创建之后，我们在 console 中打印了 objectStore.autoIncrement 的值。想查看完整的例子，请查看我们的To-do Notifications应用（查看在线例子）。

```js
// Let us open our database
var DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onsuccess = function (event) {
  note.innerHTML += "<li>Database initialised.</li>";

  // store the result of opening the database in the db variable.
  // This is used a lot below
  db = DBOpenRequest.result;

  // Run the addData() function to add the data to the database
  addData();
};

function addData() {
  // Create a new object ready to insert into the IDB
  var newItem = [
    {
      taskTitle: "Walk dog",
      hours: 19,
      minutes: 30,
      day: 24,
      month: "December",
      year: 2013,
      notified: "no",
    },
  ];

  // open a read/write db transaction, ready for adding the data
  var transaction = db.transaction(["toDoList"], "readwrite");

  // report on the success of the transaction completing, when everything is done
  transaction.oncomplete = function (event) {
    note.innerHTML += "<li>Transaction completed.</li>";
  };

  transaction.onerror = function (event) {
    note.innerHTML +=
      "<li>Transaction not opened due to error. Duplicate items not allowed.</li>";
  };

  // create an object store on the transaction
  var objectStore = transaction.objectStore("toDoList");
  console.log(objectStore.autoIncrement);

  // Make a request to add our newItem object to the object store
  var objectStoreRequest = objectStore.add(newItem[0]);

  objectStoreRequest.onsuccess = function (event) {
    // report the success of our request
    note.innerHTML += "<li>Request successful.</li>";
  };
}
```

规范
--

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-autoincrement① |

浏览器兼容性
------

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

相关内容
----

* 使用 IndexedDB
* 开始学习事务 transactions: `IDBDatabase`
* 使用事务 transactions: `IDBTransaction`
* key 值域 range 的使用：`IDBKeyRange`
* 检索、修改：`IDBObjectStore`
* 使用游标：`IDBCursor`
* 相关例子：To-do Notifications (view example live.)


IDBObjectStore.get() - Web API 接口参考

IDBObjectStore.get()
====================

`IDBObjectStore` 的接口 \*\*`get()`\*\*方法 返回 `IDBRequest` 对象，并在“单独的线程（separate thread）”中返回由指定键选择的“对象储存（object store）” 。这用于从对象储存检索特定记录。

如果成功找到值，则会创建其值的结构化克隆，并设置为“请求对象（request object）”的 `result` 。

**备注：** This method produces the same result for: a) a record that doesn't exist in the database and b) a record that has an undefined value. To tell these situations apart, call the `openCursor()` method with the same key. That method provides a cursor if the record exists, and no cursor if it does not.

**备注：** 此特性在 Web Worker 中可用

语法
--
```

var request = objectStore.get(key);
```

### 参数

key

标识要检索的记录的键或键范围。

### 返回值

触发与此操作相关的后续事件的 `IDBRequest` 对象。

### 异常

此方法可能会引发以下类型之一的 `DOMException` :

| Exception | Description |
| --- | --- |
| TransactionInactiveError | This `IDBObjectStore`'s transaction is inactive. |
| DataError | The key or key range provided contains an invalid key. |
| `InvalidStateError` | The `IDBObjectStore` has been deleted or removed. |

例子
--

在以下的代码段中，我们在数据库上打开一个“读/写 事务（read/write transaction）”，并使用 `get()` 从“对象储存（object store）”中获取一个特定的记录——一个带有“Walk dog”键的示例记录。一旦检索到这个数据对象，你就可以使用普通的 JavaScript 更新它，然后使用 `IDBObjectStore.put` 操作将其放回数据库。有关完整的工作示例，查看我们的 To-do Notifications app (view example live.)

```js
// Let us open our database
var DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onsuccess = function (event) {
  note.innerHTML += "<li>Database initialised.</li>";

  // store the result of opening the database in the db variable.
  // This is used a lot below
  db = DBOpenRequest.result;

  // Run the getData() function to get the data from the database
  getData();
};

function getData() {
  // open a read/write db transaction, ready for retrieving the data
  var transaction = db.transaction(["toDoList"], "readwrite");

  // report on the success of the transaction completing, when everything is done
  transaction.oncomplete = function (event) {
    note.innerHTML += "<li>Transaction completed.</li>";
  };

  transaction.onerror = function (event) {
    note.innerHTML +=
      "<li>Transaction not opened due to error: " + transaction.error + "</li>";
  };

  // create an object store on the transaction
  var objectStore = transaction.objectStore("toDoList");

  // Make a request to get a record by key from the object store
  var objectStoreRequest = objectStore.get("Walk dog");

  objectStoreRequest.onsuccess = function (event) {
    // report the success of our request
    note.innerHTML += "<li>Request successful.</li>";

    var myRecord = objectStoreRequest.result;
  };
}
```

规范
--

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-get① |

浏览器兼容性
------

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

参见
--

* 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 example live.)


IDBObjectStore.add() - Web API 接口参考

IDBObjectStore.add()
====================

`IDBObjectStore` 接口中的 **`add()`** 方法返回一个 `IDBRequest` 对象，在单独的线程中创建一个结构（structured clone）化克隆值，并且在对象存储中存储这个克隆值。这个方法用作在一个对象存储中添加一条新的记录。

要确定添加操作是否成功完成，可以监听事务的 `complete` 事件。除了 `IDBObjectStore.add` 请求 `success` 事件之外，因为事务在成功被触发后仍然可能失败。换句话说，成功事件只有在事务成功排队后才会触发。

**`add()`** 方法是唯一的插入方法。如果以关键字参数作为主键的一条记录已经存在在存储对象中，这时在返回的请求对象中 `ConstrainError` 错误事件将被触发。对于更新存在的记录，你应该使用 `IDBObjectStore.put` 方法替代它。

**备注：** 此特性在 Web Worker 中可用

语法
--
```

var request = objectStore.add(value);
var request = objectStore.add(value, key);
```

### 参数

value

需要存储的值。

key 可选

关键字用于识别记录。如果未指明，即为空。

### 返回

一个 `IDBRequest` 对象，在该操作对象中触发与此相关的后续事件。

### 异常

这个方法可能导致以下类型中的一个 `DOMException` :

| Exception | Description |
| --- | --- |
| `ReadOnlyError` | 与此操作相关联的事务处于只读模式。 |
| `TransactionInactiveError` | 当前 `IDBObjectStore` 事务不可用。 |
| `DataError` | 适用于以下任何条件：* 对象存储使用内联键或者拥有密钥生成器（键生成器），并且提供了键参数。
* 对象存储使用外联键或者没有密钥生成器（键生成器），并且没有提供键参数。
* 对象存储使用内联键但是没有密钥生成器（键生成器），并且对象存储的键路径不会产生一个有效的键值。
* 键参数已经被提供，但是不包含一个有效的键。
 |
| `InvalidStateError` | `IDBObjectStore` 已经被删除或者移除。 |
| `DataCloneError` | 通过内部结构的克隆算法，被存储的数据无法被克隆 |
| `ConstraintError` | 因为主键违法规定导致的插入操作失败（由于已存在的记录使用了相同的主键值）。 |

示例
--

在以下的代码片段中，在我们数据库中打开一个 read/write（读写）事务和使用 `add()` 方法添加一些数据到存储对象中。还要注意附加到事务事件处理程序的函数，这些函数用于报告事务打开成功或失败时的结果。完整的示例代码，请查看我们的 To-do Notifications 应用（在线查看示例）。

```js
// Let us open our database
var DBOpenRequest = window.indexedDB.open("toDoList", 4);

DBOpenRequest.onsuccess = function (event) {
  note.innerHTML += "<li>Database initialised.</li>";

  // store the result of opening the database in the db variable.
  // This is used a lot below
  db = DBOpenRequest.result;

  // Run the addData() function to add the data to the database
  addData();
};

function addData() {
  // Create a new object ready to insert into the IDB
  var newItem = [
    {
      taskTitle: "Walk dog",
      hours: 19,
      minutes: 30,
      day: 24,
      month: "December",
      year: 2013,
      notified: "no",
    },
  ];

  // open a read/write db transaction, ready for adding the data
  var transaction = db.transaction(["toDoList"], "readwrite");

  // report on the success of the transaction completing, when everything is done
  transaction.oncomplete = function (event) {
    note.innerHTML += "<li>Transaction completed.</li>";
  };

  transaction.onerror = function (event) {
    note.innerHTML +=
      "<li>Transaction not opened due to error. Duplicate items not allowed.</li>";
  };

  // create an object store on the transaction
  var objectStore = transaction.objectStore("toDoList");

  // Make a request to add our newItem object to the object store
  var objectStoreRequest = objectStore.add(newItem[0]);

  objectStoreRequest.onsuccess = function (event) {
    // report the success of our request
    note.innerHTML += "<li>Request successful.</li>";
  };
}
```

Specification
-------------

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-add① |

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 example live.)


IDBObjectStore.openCursor - Web API 接口参考

IDBObjectStore.openCursor
=========================

`IDBObjectStore` 的 `openCursor()` 方法 返回一个`IDBRequest` 对象，并在一个单独的线程中，返回一个新的 `IDBCursorWithValue` (en-US) 对象。此方法目的是用一个游标来遍历一个对象存储空间。

若要确认此操作是否成功完成，请监听结果的 `success` 事件。

**备注：** 此特性在 Web Worker 中可用

语法
--

```js
var request = ObjectStore.openCursor(query, direction);
```

### 参数

query 可选

要查询的键或者 `IDBKeyRange` 。如果传一个有效的键，则会默认为只包含此键的范围。如果此参数不传值，则默认为一个选择了该对象存储空间全部记录的键范围。

direction 可选

一个 `IDBCursorDirection` 来告诉游标要移动的方向。有效的值有 `"next"` 、`"nextunique"` 、`"prev"` 和 `"prevunique"`。默认值是 `"next"`。

### 返回

一个 `IDBRequest` 对象，在此对象上触发与此操作相关的后续事件。

### 异常

此方法可能引起以下类型之一的 `DOMException` ：

| 异常 | 描述 |
| --- | --- |
| `InvalidStateError` | 此 `IDBObjectStore` 或`IDBIndex` 已被删除。 |
| `TransactionInactiveError` | 此 `IDBObjectStore` 的事务处于非活动状态。 |
| `DataError` | 指定的键或键范围无效。 |

例子
--

在下面这个简单的片段中，我们创建一个事务，检索一个对象存储空间，然后用一个游标去遍历该对象存储空间的所有记录：

```js
var transaction = db.transaction("name", "readonly");
var objectStore = transaction.objectStore("name");
var request = objectStore.openCursor();
request.onsuccess = function (event) {
  var cursor = event.target.result;
  if (cursor) {
    // cursor.value 包含正在被遍历的当前记录
    // 这里你可以对 result 做些什么
    cursor.continue();
  } else {
    // 没有更多 results
  }
};
```

规范
--

| Specification |
| --- |
| Indexed Database API 3.0 # ref-for-dom-idbobjectstore-opencursor② |

浏览器兼容性
------

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

参见
--

* 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 example live.)


ResizeObserver.observe() - Web API 接口参考

ResizeObserver.observe()
========================

`ResizeObserver` 接口的 **`observe()`** 方法用于监听指定的 `Element` 或 `SVGElement`。

语法
--

```js
observe(target)
observe(target, options)
```

### 参数

`target`

对要监听的 `Element` 或 `SVGElement` 的引用。

`options` 可选

一个可选的对象，允许你为监听的对象设置参数。目前，这只有一个参数：

`box`

设置 observer 将监听的盒模型。可能的值是：

`content-box`（默认）

CSS 中定义的内容区域的大小。

`border-box`

CSS 中定义的边框区域的大小。

`device-pixel-content-box`

在对元素或其祖先应用任何 CSS 转换之前，CSS 中定义的内容区域的大小，以设备像素为单位。

### 返回值

无（`undefined`）。

### 异常

无。

示例
--

以下片段取自 resize-observer-text.html（见源码）示例：

```js
const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      // Checking for chrome as using a non-standard array
      if (entry.contentBoxSize[0]) {
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize[0].inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize[0].inlineSize / 600,
 )}rem`;
      } else {
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize.inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize.inlineSize / 600,
 )}rem`;
      }
    } else {
      h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentRect.width / 200,
 )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }
  console.log("Size changed");
});

resizeObserver.observe(divElem);
```

带有一个可选的对象的 `observe()` 看起来像这样：

```js
resizeObserver.observe(divElem, { box: "border-box" });
```

规范
--

| Specification |
| --- |
| Resize Observer # dom-resizeobserver-observe |

浏览器兼容性
------

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


ResizeObserver.unobserve() - Web API 接口参考

ResizeObserver.unobserve()
==========================

`ResizeObserver` 接口的 **`unobserve()`** 方法结束对指定的 `Element` 或 `SVGElement` 的监听。

语法
--

```js
unobserve(target)
```

### 参数

`target`

对不要监听的 `Element` 或 `SVGElement` 的引用。

### 返回值

无（`undefined`）。

### 异常

无。

示例
--

以下片段取自 resize-observer-text.html（见源码）示例：

```js
const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      // Checking for chrome as using a non-standard array
      if (entry.contentBoxSize[0]) {
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize[0].inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize[0].inlineSize / 600,
 )}rem`;
      } else {
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize.inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize.inlineSize / 600,
 )}rem`;
      }
    } else {
      h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentRect.width / 200,
 )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }
  console.log("Size changed");
});

resizeObserver.observe(divElem);

checkbox.addEventListener("change", () => {
  if (checkbox.checked) {
    resizeObserver.observe(divElem);
  } else {
    resizeObserver.unobserve(divElem);
  }
});
```

参考
--

| Specification |
| --- |
| Resize Observer # dom-resizeobserver-unobserve |

浏览器兼容性
------

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


ResizeObserver() - Web API 接口参考

ResizeObserver()
================

**`ResizeObserver`** 构造函数创建一个新的 `ResizeObserver` 对象，它可以用于监听 `Element` 内容盒或边框盒或者 `SVGElement` 边界尺寸的大小。

语法
--

```js
new ResizeObserver(callback)
```

### 参数

`callback`

每当观测的元素调整大小时，调用该函数。该函数接收两个参数：

`entries`

一个 `ResizeObserverEntry` 对象数组，可以用于获取每个元素改变后的新尺寸。

`observer`

对 `ResizeObserver` 自身的引用，因此需要它的时候，你要从回调函数的内部访问。例如，这可用于在达到特定的情况时，自动取消对观察者的监听，但如果你不需要它，可以省略它。

回调通常遵循以下模式：

```js
function callback(entries, observer) {
  for (const entry of entries) {
    // Do something to each entry
    // and possibly something to the observer itself
  }
}
```

示例
--

以下片段取自 resize-observer-text.html（见源码）示例：

```js
const resizeObserver = new ResizeObserver((entries) => {
  for (const entry of entries) {
    if (entry.contentBoxSize) {
      if (entry.contentBoxSize[0]) {
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize[0].inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize[0].inlineSize / 600,
 )}rem`;
      } else {
        // legacy path
        h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentBoxSize.inlineSize / 200,
 )}rem`;
        pElem.style.fontSize = `${Math.max(
 1,
 entry.contentBoxSize.inlineSize / 600,
 )}rem`;
      }
    } else {
      h1Elem.style.fontSize = `${Math.max(
 1.5,
 entry.contentRect.width / 200,
 )}rem`;
      pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
    }
  }
  console.log("Size changed");
});

resizeObserver.observe(divElem);
```

规范
--

| Specification |
| --- |
| Resize Observer # dom-resizeobserver-resizeobserver |

浏览器兼容性
------

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


ResizeObserver.disconnect() - Web API 接口参考

ResizeObserver.disconnect()
===========================

`ResizeObserver` 接口的 **`disconnect()`** 方法取消所有的对 `Element` 或 `SVGElement` 目标的监听。

语法
--

```js
disconnect()
```

### 参数

无。

### 返回值

无（`undefined`）。

### 异常

无。

示例
--

```js
btn.addEventListener("click", () => {
  resizeObserver.disconnect();
});
```

规范
--

| Specification |
| --- |
| Resize Observer # dom-resizeobserver-disconnect |

浏览器兼容性
------

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


HTMLIFrameElement.contentWindow - Web API 接口参考

HTMLIFrameElement.contentWindow
===============================

**`contentWindow`** 属性返回当前HTMLIFrameElement的Window对象。你可以使用这个`Window` 对象去访问这个 iframe 的文档和它内部的 DOM. 这个是可读属性，但是它的属性像全局`Window` 一样是可以操作的。

关于 contentWindow 的示例
--------------------

```js
var x = document.getElementsByTagName("iframe")[0].contentWindow;
//x = window.frames[0];

x.document.getElementsByTagName("body")[0].style.backgroundColor = "blue";
// this would turn the 1st iframe in document blue.
```

规范
--

| Specification |
| --- |
| HTML Standard # dom-iframe-contentwindow |

浏览器兼容性
------

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


Text.wholeText - Web API 接口参考

Text.wholeText
==============

该 **`Text.wholeText`** 只读属性返回`Text` (en-US)逻辑上相邻的节点的所有文本。文本按文档顺序连接。这允许指定任何文本节点并获取所有相邻文本作为单个字符串。

Syntax
------
```

str = textnode.wholeText;
```

Notes and example
-----------------

假设你的网页上有如下的简单文本 (包括其中为了格式化代码而添加的一些空格), 其 DOM 节点 被储存在变量 `para` 中：

```html
<p>
  Thru-hiking is great! <strong>No insipid election coverage!</strong> However,
  <a href="http://en.wikipedia.org/wiki/Absentee\_ballot">casting a ballot</a> is
  tricky.
</p>
```

你觉得你不喜欢中间的句子，所以你移除了它：

```js
para.removeChild(para.childNodes[1]);
```

过了一会，你又决定给“Thru-hiking is great, but casting a ballot is tricky.”这句换个说法，*同时保留超链接*。所以你尝试以下代码：

```js
para.firstChild.data = "Thru-hiking is great, but ";
```

一切妥当，是么？*不!* 这会使你移除 `strong` 元素，而被删掉的句子分隔了两个文本节点。一个是第一句，一个是最后一个单词。相反，你现在获得如下效果：

```html
<p>
  Thru-hiking is great, but However,
  <a href="http://en.wikipedia.org/wiki/Absentee\_ballot">casting a ballot</a> is
  tricky.
</p>
```

实际上，你更倾向于将这些相邻扽文本节点作为同一文本节点。这就是 `wholeText` 的用武之地：如果你有许多相邻的文本节点，你可以通过`wholeText`访问这些节点里的所有内容。让我们假设你从未犯过最后一个错误。在这种情况下，我们有：

```js
assert(para.firstChild.wholeText == "Thru-hiking is great! However, ");
```

`wholeText` 只是文本节点的一个属性，特可以返回连接了所有相邻 (i.e. 没有被其他元素边界分开) 文本节点数据的字符串。

现在让我们回到最初的问题。我们想做的是用新的文本替代旧的文本。这就是 `replaceWholeText()` (en-US) 用处所在：

```js
para.firstChild.replaceWholeText("Thru-hiking is great, but ");
```

我们移除了所有的相邻文本节点 (所有构成 whole text 的文本节点) 除了调用`replaceWholeText()` 的，并且把剩余的文本改成了新文本。我们现在所得到的是这样的：

```html
<p>
  Thru-hiking is great, but
  <a href="http://en.wikipedia.org/wiki/Absentee\_ballot">casting a ballot</a> is
  tricky.
</p>
```

有时候使用 whole-text 功能同时使用`Node.textContent` 或长期支持的 `Element.innerHTML`; 可以得到更好的处理。如果你需要处理一个元素内的混合内容，正如本文所介绍的，`wholeText` 和 `replaceWholeText()` 是有用的。

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

| Specification |
| --- |
| DOM Standard # ref-for-dom-text-wholetext① |

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

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

See also
--------

* The `Text` (en-US) interface it belongs to.


Text.splitText() - Web API 接口参考

Text.splitText()
================

**`Text.splitText()`** 方法可以根据指定的偏移量将一个 `Text` (en-US) 节点分割成前后两个独立的兄弟节点。

如果指定的偏移量刚好等于原文本节点所包含字符串的长度，则返回一个内容为空的文本节点。

分割后的文本节点还可以使用`Node.normalize`方法来合并。

语法
--
```

newNode = textNode.splitText(offset)
```

### 参数

`offset`

在中断文本节点前的索引。

### 返回值

返回一个新创建的 `Text` (en-US) 节点，该节点包含了 the text after the specified offset point.

### 异常

INDEX\_SIZE\_ERR

如果指定的偏移量小于 0 或者大于原文本节点中所包含字符串的长度，则抛出这个异常。

NO\_MODIFICATION\_ALLOWED\_ERR

如果，原文本节点只读，则抛出这个异常。

示例
--

下面的例子中，一个 `<p>` 元素所包含的文本节点将会被分割成两个文本节点，然后在这两个节点中间插入一个 `<span>` 元素。

### HTML

```html
<p id="p">foobar</p>
```

### JavaScript

```js
const p = document.getElementById("p");

// 将 <p> 的内容读取为一个文本节点
const foobar = p.firstChild;

// 将原来的文本节点分割成为内容分别为 foo 和 bar 的两个文本节点
const bar = foobar.splitText(3);

// 创建一个包含了内容为 ' new content ' 的文本节点的 <u> 元素
const u = document.createElement("u");
u.appendChild(document.createTextNode(" new content "));

// 将 <u> 元素插入到后一个文本节点 'bar' 的前面
p.insertBefore(u, bar);

// 现在，HTML 结构就变成了 <p id="p">foo <span>span contents</span> bar</p>
```

### 结果

规范
--

| Specification |
| --- |
| DOM Standard # ref-for-dom-text-splittext① |

浏览器兼容性
------

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

参见
--

* The `Text` (en-US) interface it belongs to.
* The opposite method: `Node.normalize`.


Text：Text() 构造函数 - Web API 接口参考

Text：Text() 构造函数
================

**`Text()`** 构造函数返回一个新创建的 `Text` (en-US) 对象，其文本内容为参数中给出的可选字符串。

语法
--

```js
new Text()
new Text(string)
```

### 参数

* `string` 可选
### 返回值

一个新的 `Text` (en-US) 对象，包含参数 `string` 的内容，如果没有给定参数，则为空字符串。

示例
--

```js
let text = new Text("Test");
```

规范
--

| Specification |
| --- |
| DOM Standard # ref-for-dom-text-text① |

浏览器兼容性
------

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

参见
--

* DOM API


HTMLSlotElement.assignedSlot - Web API 接口参考

HTMLSlotElement.assignedSlot
============================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`assignedSlot`** 是 `Text` (en-US) 接口的属性，返回与该元素相关联的`HTMLSlotElement` .

Syntax
------
```

var htmlSlotElement = text.assignedSlot
```

### Value

一个 `HTMLSlotElement` 对象。

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

| Specification |
| --- |
| DOM Standard # dom-slotable-assignedslot |

Browser Compatibility
---------------------

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


源私有文件系统 - Web API 接口参考

源私有文件系统
=======

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

源私有文件系统（OPFS）是作为文件系统 API 的一部分提供的一个存储端点。它是页面所属的源专用的，并且不像常规文件系统那样对用户可见。它提供了对一种特殊类型文件的访问能力，这种文件经过高度性能优化，并提供对其内容的原地写入访问特性。

使用文件系统 API 处理文件
---------------

扩展自文件系统 API 的文件系统访问 API 使用选择器提供了对文件的访问能力。例如：

1. `Window.showOpenFilePicker()` 允许用户选择一个文件用于访问，文件将作为结果以一个 `FileSystemFileHandle` 对象的形式被返回。
2. 调用 `FileSystemFileHandle.getFile()` 以访问文件的内容，使用 `FileSystemFileHandle.createWritable()` / `FileSystemWritableFileStream.write()` 来修改内容。
3. 调用 `FileSystemHandle.requestPermission({mode: 'readwrite'})` 来请求用户的权限以保存更改。
4. 如果用户接受了权限请求，更改就会保存回原文件。

这个方法可行，但是有一些限制。这些更改是对用户可见的文件系统进行的，所以会有很多适当的安全性检查（比方说 Chrome 的安全浏览）来防止恶意内容被写入到文件系统。这些写入不是原地的，会先写入到一个临时文件。除非通过了所有的安全性检查，否则原文件不会被修改。

因此，这些操作会相当缓慢。在你进行小规模的文本更新时没那么明显，但是当进行像 SQLite 数据库更改这样的更显著、更大规模的文件更新时就会遇到性能问题。

OPFS 是怎么解决这些问题的？
----------------

OPFS 提供了页面所属源私有的、对用户不可见的、底层的逐字节文件访问能力。因此它不需要经过与调用文件系统访问 API 所需的一系列相同的安全性检查和授权，而且比文件系统访问 API 更快。它还有一套同步调用方法可用（其他的文件系统 API 调用是异步的），但只能在 web worker 中运行，这样就不会阻塞主线程。

概括 OPFS 和用户可见文件系统的不同：

* OPFS 和其他源分区存储机制（例如 IndexedDB API）一样，受到浏览器存储配额限制。你可以通过 `navigator.storage.estimate()` 来获得 OPFS 所用的存储空间的容量。
* 清除站点的存储数据会删除 OPFS。
* 访问 OPFS 中的文件不需要权限提示和安全性检查。
* 浏览器会把 OPFS 的内容持久化保存在磁盘的某个位置，但你不能指望能够一一对应地找到创建出的文件。OPFS 对用户不可见。
如何访问 OPFS？
----------

想要访问 OPFS，你首先要调用 `navigator.storage.getDirectory()` (en-US) 方法。返回一个代表 OPFS 根目录的 `FileSystemDirectoryHandle` 对象的引用。

在主线程中操作 OPFS
------------

在主线程中访问 OPFS 时，你要使用基于 `Promise` 的异步 API。你可以调用代表 OPFS 根目录（以及其中被创建的子目录）的 `FileSystemDirectoryHandle` 对象上的 `FileSystemDirectoryHandle.getFileHandle()` 和 `FileSystemDirectoryHandle.getDirectoryHandle()` 方法来分别访问文件（`FileSystemFileHandle`）和目录（`FileSystemDirectoryHandle`）。

**备注：** 在上述方法中传入 `{ create: true }` 会在文件或文件夹不存在时创建相应的文件或文件夹。

```js
// 创建层级结构的文件和文件夹
const fileHandle = await opfsRoot.getFileHandle("my first file", {
  create: true,
});
const directoryHandle = await opfsRoot.getDirectoryHandle("my first folder", {
  create: true,
});
const nestedFileHandle = await directoryHandle.getFileHandle(
  "my first nested file",
  { create: true },
);
const nestedDirectoryHandle = await directoryHandle.getDirectoryHandle(
  "my first nested folder",
  { create: true },
);

// 通过文件名和文件夹名访问已有的文件和文件夹
const existingFileHandle = await opfsRoot.getFileHandle("my first file");
const existingDirectoryHandle =
  await opfsRoot.getDirectoryHandle("my first folder");
```

### 读取文件

1. 调用 `FileSystemDirectoryHandle.getFileHandle()` 以返回一个 `FileSystemFileHandle` 对象。
2. 调用 `FileSystemFileHandle.getFile()` 方法返回一个 `File` 对象。这是一种特化的 `Blob` 对象，所以可以像操作其他 `Blob` 对象那样去操作它。比如，你可以通过 `Blob.text()` 直接访问其文本内容。
### 写入文件

1. 调用 `FileSystemDirectoryHandle.getFileHandle()` 以返回一个 `FileSystemFileHandle` 对象。
2. 调用 `FileSystemFileHandle.createWritable()` 方法返回一个 `FileSystemWritableFileStream` 对象，这是一种特化的 `WritableStream` 对象。
3. 调用 `FileSystemWritableFilestream.write()` 来向其写入内容。
4. 使用 `WritableStream.close()` (en-US) 关闭流。
### 删除文件或目录

你可以在父目录上调用 `FileSystemDirectoryHandle.removeEntry()`，向它传入你想要删除的项的名称：

```js
directoryHandle.removeEntry("my first nested file");
```

你也可以在代表你想要删除的项目的 `FileSystemFileHandle` 或 `FileSystemDirectoryHandle` 上调用 `FileSystemHandle.remove()` 来进行删除。要删除一个文件夹和它所有的子文件夹，需要传递 `{ recursive: true }` 选项。

```js
await fileHandle.remove();
await directoryHandle.remove({ recursive: true });
```

下面提供一个快捷的方法清空整个 OPFS：

```js
await (await navigator.storage.getDirectory()).remove({ recursive: true });
```

### 列出文件夹中的内容

`FileSystemDirectoryHandle` 是一个异步迭代器。所以，你可以用 `for await…of` 循环和诸如 `entries()`、`values()` 和 `keys()` 这样的标准方法对其进行迭代。

例如：

```js
for await (let [name, handle] of directoryHandle) {
}
for await (let [name, handle] of directoryHandle.entries()) {
}
for await (let handle of directoryHandle.values()) {
}
for await (let name of directoryHandle.keys()) {
}
```

在 web worker 中操作 OPFS
---------------------

Web Worker 不会阻塞主线程，这意味着你可以在其上下文中使用同步文件访问 API。同步的 API 因其不需要处理 promise，所以更快。

你可以通过在常规的 `FileSystemFileHandle` 上调用 `FileSystemFileHandle.createSyncAccessHandle()` 来同步地处理文件：

**备注：** 虽然 `createSyncAccessHandle()` 的名称带有“Sync（同步）”字眼，但是这个方法本身是异步的。

```js
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("高速文件.txt", {
  create: true,
});
const syncAccessHandle = await fileHandle.createSyncAccessHandle();
```

返回的 `FileSystemSyncAccessHandle` 上有几个*同步的*方法可用：

* `getSize()`：返回文件的字节大小。
* `write()`：将一个缓冲区的内容写入到文件中，可选择在给定的偏移处开始写入。它会返回写入的字节数。检查返回的写入字节数可以让调用方检测并处理错误和不完整的写入。
* `read()`：读取文件的内容到一个缓冲区中，可选择在给定的偏移处开始读取。
* `truncate()`：将文件调整至给定的大小。
* `flush()`：确保文件的内容包含所有通过 `write()` 完成的修改。
* `close()`：关闭访问句柄。

这里是一个使用了上述所有方法的示例：

```js
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("fast", { create: true });
const accessHandle = await fileHandle.createSyncAccessHandle();

const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

// 将这个变量初始化为文件的大小。
let size;
// 文件当前的大小，最开始是 `0`。
size = accessHandle.getSize();
// 编码要写入文件的内容。
const content = textEncoder.encode("Some text");
// 在文件的开头写入内容。
accessHandle.write(content, { at: size });
// 强制刷入更改。
accessHandle.flush();
// 文件当前的大小，现在是 `9`（"Some text" 的长度）。
size = accessHandle.getSize();

// 编码更多要写入文件的内容。
const moreContent = textEncoder.encode("More content");
// 在文件的末尾写入内容。
accessHandle.write(moreContent, { at: size });
// 强制刷入更改。
accessHandle.flush();
// 文件当前的大小，现在是 `21`（"Some textMore content" 的长度）。
size = accessHandle.getSize();

// 准备一个长度与文件相同的数据视图。
const dataView = new DataView(new ArrayBuffer(size));

// 将整个文件读取到数据视图。
accessHandle.read(dataView);
// 打印 `"Some textMore content"`。
console.log(textDecoder.decode(dataView));

// 在数据视图中的偏移位置 9 处开始读取。
accessHandle.read(dataView, { at: 9 });
// 打印 `"More content"`。
console.log(textDecoder.decode(dataView));

// 裁去文件头 4 个字节之后的内容。
accessHandle.truncate(4);
```

浏览器兼容性
------

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

参见
--

* 源私有文件系统——web.dev


MediaQueryListEvent() - Web API 接口参考

MediaQueryListEvent()
=====================

**`MediaQueryListEvent()`** 构造函数用于创建一个新的 `MediaQueryListEvent` 对象。

语法
--

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

### 参数

`type`

一个带有该事件名字的字符串。该字符串是大小写敏感的，且浏览器通常将其设置为 `change`。

`options` 可选

一个对象，*除已定义在 `Event()`的属性外*，其还可以添加如下额外属性：

`media` 可选

一个字符串，代表着一个序列化后的媒体查询。默认值为 `""`。

`matches` 可选

一个布尔值，代表着匹配媒体查询状态；如果匹配，该值为 `true`，否则为 `false`。默认值为 `false`。

### 返回值

一个新的 `MediaQueryListEvent` 对象。

示例
--

```js
var media = "(max-width: 600px)";
var matches = true;

var myMediaQueryListEvent = new MediaQueryListEvent("change", {
  media,
  matches,
});
```

规范
--

| Specification |
| --- |
| CSSOM View Module # dom-mediaquerylistevent-mediaquerylistevent |

浏览器兼容性
------

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

参见
--

* 媒体查询
* 在代码中使用媒体查询
* `window.matchMedia()`
* `MediaQueryList`
* `MediaQueryListEvent`


使用 Notifications API - Web API 接口参考

使用 Notifications API
====================

**备注：** 此特性在 Web Worker 中可用

**安全上下文:** 此项功能仅在一些支持的浏览器的安全上下文（HTTPS）中可用。

Notifications API 允许网页或应用程序以系统级别发送在页面外部显示的通知；这样即使应用程序空闲或在后台，Web 应用程序也会向用户发送信息。本文将介绍在你自己的应用程序中使用此 API 的基础知识。

通常，系统通知是指操作系统的标准通知机制，例如，思考典型的桌面系统或移动设备如何发布通知。

![桌面通知：通过 mdn.github.io 列出待办事项 嘿！你的任务“去购物”现已过期](/zh-CN/docs/Web/API/Notifications_API/Using_the_Notifications_API/desktop-notification.png)

系统通知系统当然会因平台和浏览器而异，但无需担心，通知 API 编写得足够通用，足以与大多数系统通知系统兼容。

示例
--

Web 通知最明显的用例之一是基于 Web 的邮件或 IRC 应用程序，即使用户正在使用另一个应用程序执行其他操作，它也需要在收到新消息时通知用户。现在存在许多这样的例子，例如 Slack。

我们编写了一个现实世界的示例——一个待办事项列表应用程序——来让你更多地了解如何使用 Web 通知。它使用 IndexedDB 在本地存储数据，并在任务到期时使用系统通知通知用户。下载待办事项列表代码，或查看实时运行的应用程序。

请求权限
----

在应用程序可以发送通知之前，用户必须授予应用程序这样做的权利。当 API 尝试与网页之外的内容进行交互时，这是一个常见的要求——用户至少需要专门授予该应用程序显示通知的权限一次，从而让用户控制哪些应用程序或站点允许显示通知。

由于过去滥用推送通知，网络浏览器和开发人员已开始实施策略来帮助缓解此问题。你应该仅请求同意显示通知以响应用户手势（例如：单击按钮）。这不仅是最佳实践（你不应该向用户发送他们不同意的通知），而且未来的浏览器将明确禁止未响应用户手势而触发的通知权限请求。例如，Firefox 从版本 72 开始就已经这样做了，Safari 也已经这样做了一段时间了。

此外，在 Chrome 和 Firefox 中，除非网站是安全上下文（即 HTTPS），否则你根本无法请求通知，并且你不能再从跨源 `<iframe>` 请求通知权限。

### 检查当前权限状态

你可以通过检查只读属性 `Notification.permission` 的值来查看你是否已经有权限。该属性的值将会是下列三个之一：

`default`

用户还未被询问是否授权，所以通知不会被显示。

`granted`

表示之前已经询问过用户，并且用户已经授予了显示通知的权限。

`denied`

用户已经明确地拒绝了显示通知的权限。

### 获得权限

如果尚未授予显示通知的权限，则应用程序需要使用 `Notification.requestPermission()` 方法向用户请求此权限。在最简单的形式中，我们只包含以下内容：

```js
Notification.requestPermission().then((result) => {
  console.log(result);
});
```

这使用了该方法的基于 promise 的版本。如果你想支持旧版本，你可能必须使用旧的回调版本，如下所示：

```js
Notification.requestPermission((result) => {
  console.log(result);
});
```

回调版本可以选择接受一个回调函数，一旦用户响应了显示权限的请求，就会调用该回调函数。

**备注：** 目前无法可靠地对 `Notification.requestPermission` 是否支持基于 Promise 的版本进行特性测试。如果你需要支持较旧的浏览器，只需使用基于回调的版本——尽管它已被弃用，但它仍然可以在新浏览器中使用。有关更多信息，请参阅浏览器兼容性表。

### 示例

在我们的待办事项列表演示中，我们包含一个“启用通知”按钮，按下该按钮时，会请求应用程序的通知权限。

```html
<button id="enable">Enable notifications</button>
```

单击此按钮将调用 `askNotificationPermission()` 函数：

```js
function askNotificationPermission() {
  // 实际询问权限的函数
  function handlePermission(permission) {
    // 根据用户的回答将按钮设置为显示或隐藏
    notificationBtn.style.display =
      Notification.permission === "granted" ? "none" : "block";
  }

  // 让我们检查一下浏览器是否支持通知
  if (!("Notification" in window)) {
    console.log("此浏览器不支持通知。");
  } else {
    Notification.requestPermission().then((permission) => {
      handlePermission(permission);
    });
  }
}
```

首先查看第二个主要块，你会发现我们首先检查是否支持通知。如果支持的话，我们接着运行基于 Promise 的 `Notification.requestPermission()` 版本，否则在控制台输出一条消息。

为了避免重复代码，我们在 `handlePermission()` 函数中存储了一些内部代码，这是该代码段中的第一个主要块。在这里，我们明确设置了 `Notification.permission` 值（某些旧版本的 Chrome 无法自动执行此操作），并根据用户在权限对话框中选择的内容显示或隐藏按钮。如果已经授予许可，我们不想显示它，但如果用户选择拒绝许可，我们希望给他们稍后改变主意的机会。

**备注：** 在 Chrome 的 37 版本之前，其不允许你在 `load` 事件处理程序中调用 `Notification.requestPermission()`（请参阅 [issue 274284](https://crbug .com/274284)）。

创建通知
----

创建通知很简单，只需要用 `Notification` 构造方法。这个构造方法需要一个用来显示在通知内的标题以及一些用来增强通知的选项，例如 `icon` 或文本 `body`。

例如，在待办事项列表示例中，我们使用以下代码片段在需要时创建通知（在 `createNotification()` 函数中找到）：

```js
const img = "/to-do-notifications/img/icon-128.png";
const text = `嘿！您的任务“${title}”现已过期。`;
const notification = new Notification("待办列表", { body: text, icon: img });
```

关闭通知
----

使用 `close()` 删除不再与用户相关的通知（例如，对于消息应用程序，用户已经阅读了网页上的通知） ，或者以下歌曲已在音乐应用程序中播放以通知歌曲更改）。大多数现代浏览器会在一段时间（大约四秒）后自动关闭通知，但这不是你通常应该关心的事情，因为它取决于用户和用户代理。删除通知也可能发生在操作系统级别，用户应该对此保持控制。旧版本的 Chrome 不会自动删除通知，因此你可以在 `setTimeout()` 之后执行此操作，以免从其他浏览器的通知托盘中删除通知。

```js
const n = new Notification("我的歌");
document.addEventListener("visibilitychange", () => {
  if (document.visibilityState === "visible") {
    // 该标签页已对用户可见，因此可以清除现已过时的通知。
    n.close();
  }
});
```

**备注：** 此 API 不应仅用于在固定延迟后（在现代浏览器上）从屏幕上删除通知，因为此方法还会从任何通知托盘中删除通知，从而阻止用户在最初显示通知后与其进行交互。

**备注：** 当你收到“关闭”事件时，无法保证是用户关闭了通知。这符合规范，其中规定：当底层通知平台或用户关闭通知时，必须运行其关闭步骤。

通知事件
----

`Notification` 实例上会触发四个事件：

`click`

当用户点击通知时触发。

`close`

在通知关闭后触发。

`error`

如果通知出现问题则触发；这通常是因为由于某种原因无法显示通知。

`show`

当向用户显示通知时触发。

可以使用 `onclick`、`onclose`、`onerror` 和 `onshow` 处理器跟踪这些事件。因为 `Notification` 也继承自 `EventTarget`，所以可以使用 `addEventListener()` 方法。

替换现有通知
------

用户通常不希望在短时间内收到大量通知——例如，如果消息应用程序通知用户每条传入消息，而这些消息发送量很大，该怎么办？为了避免向用户发送太多通知，可以修改待处理通知队列，用新通知替换单个或多个待处理通知。

为此，可以向任何新通知添加标签。如果通知已具有相同标签且尚未显示，则新通知将替换先前的通知。如果已显示具有相同标签的通知，则关闭上一个通知并显示新的通知。

### 标签示例

假设有以下基本 HTML：

```html
<button>提醒我！</button>
```

可以通过这种方式处理多个通知：

```js
window.addEventListener("load", () => {
  const button = document.querySelector("button");

  if (window.self !== window.top) {
    // 确保如果我们的文档位于框架中，我们会让用户首先在自己的选项卡或窗口中打开它。否则，它将无法请求发送通知的权限
    button.textContent = "查看上面示例代码的实时运行结果";
    button.addEventListener("click", () => window.open(location.href));
    return;
  }

  button.addEventListener("click", () => {
    if (Notification?.permission === "granted") {
      // 如果用户同意收到通知让我们尝试发送十个通知
      let i = 0;
      // 使用间隔以避免某些浏览器（包括 Firefox）在特定时间内出现过多通知时会阻止通知
      const interval = setInterval(() => {
        // 由于 tag 参数，我们应该只能看到“Hi！9”通知
        const n = new Notification(`Hi! ${i}`, { tag: "soManyNotification" });
        if (i === 9) {
          clearInterval(interval);
        }
        i++;
      }, 200);
    } else if (Notification && Notification.permission !== "denied") {
      // 如果用户没有告诉他们是否想要收到通知（注意：由于 Chrome，我们不确定是否设置了权限属性），因此检查“默认”值是不安全的。
      Notification.requestPermission().then((status) => {
        // 如果用户同意
        if (status === "granted") {
          let i = 0;
          // 使用间隔以避免某些浏览器（包括 Firefox）在特定时间内出现过多通知时会阻止通知
          const interval = setInterval(() => {
            // 由于 tag 参数，我们应该只能看到“Hi！9”通知
            const n = new Notification(`Hi! ${i}`, {
              tag: "soManyNotification",
            });
            if (i === 9) {
              clearInterval(interval);
            }
            i++;
          }, 200);
        } else {
          // 否则，我们可以回退到常规模式提醒
          alert("Hi!");
        }
      });
    } else {
      // 如果用户拒绝收到通知，我们可以退回到常规模式提醒
      alert("Hi!");
    }
  });
});
```

### 结果

规范
--

| Specification |
| --- |
| Notifications API Standard # api |

浏览器兼容性
------

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

参见
--

* `Notification`


Clipboard：write() 方法 - Web API 接口参考

Clipboard：write() 方法
====================

`Clipboard` 的方法 **`write()`** 写入图片等任意的数据到剪贴板。这个方法可以用于实现剪切和复制的功能。

当页面位于活动选项卡中时，权限 API (en-US) 中的 `"clipboard-write"` 权限会自动授予该页面。

**备注：** 浏览器对这个异步剪贴板的 API 仍然在讨论中。所以在使用它之前请检查浏览器兼容性和剪贴板可用性以获得更多的兼容性信息。

**备注：** 为了与 Google Chrome 浏览器保持一致，Firefox 只允许此函数处理文本、HTML 和 PNG 数据。

语法
--

```js
write(data)
```

### 参数

`data`

包含要写入剪贴板的数据的 `ClipboardItem` (en-US) 对象数组。

### 返回值

当数据被写入到剪贴板的时候，`Promise` resolve 回调被执行。如果剪贴板不能完成剪贴操作，`Promise` reject 回调被执行。

示例
--

以下示例代码将展示如何将剪贴板的内容替换为指定的字符串。

```js
function setClipboard(text) {
  const type = "text/plain";
  const blob = new Blob([text], { type });
  const data = [new ClipboardItem({ [type]: blob })];

  navigator.clipboard.write(data).then(
    () => {
      /\* success \*/
    },
    () => {
      /\* failure \*/
    },
  );
}
```

代码首先创建了一个新的 `Blob` 对象，需要使用该对象来构造 `ClipboardItem` (en-US) 对象，并将其发送到剪贴板。`Blob` 构造函数接收我们要复制的内容及类型，一个 `Blob` 对象可以有不同的来源，例如 canvas。

接下来，我们创建一个新的 `ClipboardItem` (en-US) 对象，并在其中放置 blob，以写入到剪贴板。传递给 `ClipboardItem` (en-US) 构造函数的对象的键名表示内容类型，值表示内容。然后调用 `write()`，并指定复制成功和失败的回调函数。

### 复制 canvas 内容至剪贴板的示例

```js
function copyCanvasContentsToClipboard(canvas, onDone, onError) {
  canvas.toBlob((blob) => {
    let data = [new ClipboardItem({ [blob.type]: blob })];

    navigator.clipboard.write(data).then(
      () => {
        onDone();
      },
      (err) => {
        onError(err);
      },
    );
  });
}
```

**备注：** 一次只能传入一个剪贴板项目。

规范
--

| Specification |
| --- |
| Clipboard API and events # dom-clipboard-write |

浏览器兼容性
------

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


Clipboard.writeText() - Web API 接口参考

Clipboard.writeText()
=====================

`Clipboard` 接口的 **`writeText()`** 方法可以写入特定字符串到操作系统的剪切板。

**备注：** 规范要求在写入剪贴板之前使用 Permissions API (en-US) 获取“剪贴板写入”权限。但是，不同浏览器的具体要求不同，因为这是一个新的 API。有关详细信息，请查看浏览器兼容性和剪贴板可用性。

语法
--
```

var promise = navigator.clipboard.writeText(newClipText)
```

### 参数

`newClipText`

The `DOMString` to be written to the clipboard.

### 返回值

一个`Promise` ，一旦剪贴板的内容被更新，它就会被解析。如果调用者没有写入剪贴板的权限，则拒绝写入剪切板（reject）

例子
--

此示例将剪贴板的内容设置为字符串“<empty clipboard>”。

```js
navigator.clipboard.writeText("<empty clipboard>").then(
  function () {
    /\* clipboard successfully set \*/
  },
  function () {
    /\* clipboard write failed \*/
  },
);
```

规范
--

| Specification |
| --- |
| Clipboard API and events # dom-clipboard-writetext |

浏览器兼容性
------

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


Clipboard.readText() - Web API 接口参考

Clipboard.readText()
====================

**`Clipboard`** 接口的 **`readText()`** 方法解析系统剪贴板的文本内容返回一个`Promise` 。

语法
--
```

var promise = navigator.clipboard.readText()
```

### 参数

None.

### 返回值

A `Promise` that resolves with a `DOMString` containing the textual contents of the clipboard. Returns an empty string if the clipboard is empty, does not contain text, or does not include a textual representation among the `DataTransfer` objects representing the clipboard's contents.

要从剪贴板中读取非文本内容，请改用`read()` (en-US)方法。你可以使用 `writeText()`将文本写入剪贴板

例子
--

此示例检索剪贴板的文本内容，并将返回的文本插入元素的内容中。

```js
navigator.clipboard
  .readText()
  .then((clipText) => (document.getElementById("outbox").innerText = clipText));
```

规范
--

| Specification |
| --- |
| Clipboard API and events # dom-clipboard-readtext |

浏览器兼容性
------

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

See also
--------

* Clipboard API
* `Clipboard.writeText()`
* `Clipboard.write()`


GlobalEventHandlers.oncuechange - Web API 接口参考

GlobalEventHandlers.oncuechange
===============================

**`oncuechange`** 属性属于 `GlobalEventHandlers`，是一个处理 `cuechange` 事件的事件处理器。当`TextTrack` (en-US)更改了当前显示的提示时，`cuechange` 事件将会触发。

语法
--

```js
element.oncuechange = handlerFunction;
var handlerFunction = element.oncuechange;
```

`handlerFunction` 可以为 `null`，也可以是一个处理指定事件的JavaScript 函数。

规范
--

| Specification |
| --- |
| HTML Standard # event-media-cuechange |
| HTML Standard # handler-texttrack-oncuechange |

浏览器兼容性
------

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

查看更多
----

* `cuechange`
* DOM 事件处理函数 (en-US)


Storage.clear() - Web API 接口参考

Storage.clear()
===============

`Storage` 接口的 **`clear()`** 方法清除给定 `Storage` 对象中存储的所有键。

语法
--

```js
clear()
```

### 参数

无。

### 返回值

无 (`undefined`)。

示例
--

下面的函数在本地存储里面创建三个数据项，然后使用 `clear()` 把它们全部移除。

```js
function populateStorage() {
  localStorage.setItem("bgcolor", "red");
  localStorage.setItem("font", "Helvetica");
  localStorage.setItem("image", "miGato.png");

  localStorage.clear();
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-clear-dev |

浏览器兼容性
------

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

相关链接
----

使用 Web Storage API


Storage.removeItem() - Web API 接口参考

Storage.removeItem()
====================

`Storage` 接口的 **`removeItem()`** 方法，当传递一个键名时，将从给定的 `Storage` 对象中删除该键（如果它存在）。Web Storage API 的 **`Storage`** 接口提供对特定域的会话或本地存储的访问。

如果没有与该给定键名匹配的项，则此方法将不执行任何操作。

语法
--

```js
removeItem(keyName)
```

### 参数

`keyName`

一个包含你要删除的键名字符串。

### 返回值

无 (`undefined`)。

示例
--

下面的函数在本地存储里面创建三个数据项，然后把 `image` 数据项移除。

```js
function populateStorage() {
  localStorage.setItem("bgcolor", "red");
  localStorage.setItem("font", "Helvetica");
  localStorage.setItem("image", "myCat.png");

  localStorage.removeItem("image");
}
```

我们可以为 session storage 做同样的事情。

```js
function populateStorage() {
  sessionStorage.setItem("bgcolor", "red");
  sessionStorage.setItem("font", "Helvetica");
  sessionStorage.setItem("image", "myCat.png");

  sessionStorage.removeItem("image");
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-removeitem-dev |

浏览器兼容性
------

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

相关链接
----

使用 Web Storage API


Storage.setItem() - Web API 接口参考

Storage.setItem()
=================

`Storage` 接口的 **`setItem()`** 方法，当传递了一个键名和值时，将会把键名添加到给定的 `Storage` 对象中，如果键名已存在，则更新其对应的值。

语法
--

```js
setItem(keyName, keyValue)
```

参数
--

`keyName`

包含要创建或更新的键名字符串。

`keyValue`

包含要创建或更新的键名对应的值字符串。

### 返回值

无 `undefined`。

### 异常

在存储已满的情况下，调用 `setItem()` 可能会抛出异常。开发人员应**始终捕获 `setItem()` 可能抛出的异常**。

示例
--

下面的函数在本地存储中创建三个数据项。

```js
function populateStorage() {
  localStorage.setItem("bgcolor", "red");
  localStorage.setItem("font", "Helvetica");
  localStorage.setItem("image", "myCat.png");
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-setitem-dev |

浏览器兼容性
------

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

参见
--

* Storage.getItem()
* Storage.removeItem()
* 使用 Web Storage API


Storage.getItem() - Web API 接口参考

Storage.getItem()
=================

`Storage` 接口的 **`getItem()`** 方法，当传递一个键名时，将返回该键的值；而如果在给定的 `Storage` 对象中不存在该键，则返回 `null`。

语法
--

```js
getItem(keyName)
```

### 参数

`keyName`

一个包含你要检索的键名字符串。

### 返回值

一个包含键值的字符串。如果该键名不存在，则返回 `null`。

示例
--

下面的函数从本地存储中获取三个数据项，然后使用他们在页面上设置自定义样式：

```js
function setStyles() {
  const currentColor = localStorage.getItem("bgcolor");
  const currentFont = localStorage.getItem("font");
  const currentImage = localStorage.getItem("image");

  document.getElementById("bgcolor").value = currentColor;
  document.getElementById("font").value = currentFont;
  document.getElementById("image").value = currentImage;

  htmlElem.style.backgroundColor = `#${currentColor}`;
  pElem.style.fontFamily = currentFont;
  imgElem.setAttribute("src", currentImage);
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-getitem-dev |

浏览器兼容性
------

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

相关链接
----

使用 Web Storage API


Storage.length - Web API 接口参考

Storage.length
==============

`Storage` 接口的只读属性 **`length`** 返回存储在一个给定的 `Storage` 对象中的数据项的数量。

值
-

`Storage` 对象中存储的数据项数量。

示例
--

下面的函数添加三个数据项到当前域名的本地存储里面，然后返回本地存储里面数据项的数量：

```js
function populateStorage() {
  localStorage.setItem("bgcolor", "yellow");
  localStorage.setItem("font", "Helvetica");
  localStorage.setItem("image", "cats.png");

  return localStorage.length; // 应该返回 3
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-length-dev |

浏览器兼容性
------

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

相关链接
----

使用 Web Storage API


Storage.key() - Web API 接口参考

Storage.key()
=============

`Storage` 接口的 **`key()`** 方法，当传递一个数字 n 时，返回给定存储对象中第 n 个键的名称。键的顺序取决于用户代理，所以你不应该依赖它。

语法
--

```js
key(index)
```

### 参数

`index`

一个整数，表示要获取的键名索引。这是一个从零开始的索引。

### 返回值

包含键名称的字符串。如果索引不存在，则返回 `null`。

示例
--

下面的函数遍历本地存储键：

```js
function forEachKey(callback) {
  for (let i = 0; i < localStorage.length; i++) {
    callback(localStorage.key(i));
  }
}
```

下面的函数遍历本地存储键，并获得每个键的设定值：

```js
for (let i = 0; i < localStorage.length; i++) {
  console.log(localStorage.getItem(localStorage.key(i)));
}
```

**备注：** 有关实际运行的例子，详见 Web Storage 演示。

规范
--

| Specification |
| --- |
| HTML Standard # dom-storage-key-dev |

浏览器兼容性
------

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

相关链接
----

使用 Web Storage API


HTMLDetailsElement: toggle event - Web API 接口参考

HTMLDetailsElement: toggle event
================================

当`<details>`元素`打开`/`关闭`状态被切换时，切换事件会触发。

| Bubbles | No |
| --- | --- |
| Cancelable | No |
| Interface | `Event` |
| Event handler property | None |
| Default Action | Toggles the `open` state of the `<details>` element. |

示例
--

此示例记录打开的章节。当章节关闭时，它们将从日志中删除。

### HTML

```html
<aside id="log">
  <b>Open chapters:</b>
  <div data-id="ch1" hidden>I</div>
  <div data-id="ch2" hidden>II</div>
  <div data-id="ch3" hidden>III</div>
</aside>
<section id="summaries">
  <b>Chapter summaries:</b>
  <details id="ch1">
    <summary>Chapter I</summary>
    Philosophy reproves Boethius for the foolishness of his complaints against
    Fortune. Her very nature is caprice.
  </details>
  <details id="ch2">
    <summary>Chapter II</summary>
    Philosophy in Fortune's name replies to Boethius' reproaches, and proves
    that the gifts of Fortune are hers to give and to take away.
  </details>
  <details id="ch3">
    <summary>Chapter III</summary>
    Boethius falls back upon his present sense of misery. Philosophy reminds him
    of the brilliancy of his former fortunes.
  </details>
</section>
```

### CSS

```css
body {
  display: flex;
  flex-direction: row-reverse;
}

#log {
  flex-shrink: 0;
  padding-left: 3em;
}

#summaries {
  flex-grow: 1;
}
```

### JavaScript

```js
function logItem(e) {
  const item = document.querySelector(`[data-id=${e.target.id}]`);
  item.toggleAttribute("hidden");
}

const chapters = document.querySelectorAll("details");
chapters.forEach((chapter) => {
  chapter.addEventListener("toggle", logItem);
});
```

### 结果

规范
--

| Specification |
| --- |
| HTML Standard # event-toggle |

浏览器兼容性
------

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


CSSRule.cssText - Web API 接口参考

CSSRule.cssText
===============

概述
**cssText** 返回样式规则所包含的实际文本。想要能够动态的设置一个样式表规则，查看使用动态样式信息。 (en-US)

语法
--
```

string = cssRule.cssText
```

例子
--

```html
<style>
 body {
 background-color: darkblue;
 }
</style>
<script>
 var stylesheet = document.styleSheets[0];
 alert(stylesheet.cssRules[0].cssText); // body { background-color: darkblue; }
</script>
```

规范
--

* DOM Level 2 Style CSS - Interface CSSStyleRule (introduced in DOM Level 2)


CSSRule.parentStyleSheet - Web API 接口参考

CSSRule.parentStyleSheet
========================

### 概述

**parentStyleSheet** 返回在当前规则中已定义的样式表对象。

### 语法
```

stylesheet = cssRule.parentStyleSheet
```

### 参数

* `stylesheet`是一个样式表对象。
### 例子
```

if ( bgRule.parentStyleSheet != mySheet ) {
   // alien style rule!
}
```

### 备注

查看 Gecko DOM Reference:event#DOM\_styleSheet\_Object 有关样式表的对象接口的详细信息。

### 规范

DOM Level 2 Style - cssRule


DataTransfer.types - Web API 接口参考

DataTransfer.types
==================

**`DataTransfer.types`** 是只读属性。它返回一个我们在`dragstart`事件中设置的拖动数据格式 (如 `字符串`) 的数组。格式顺序与拖动操作中包含的数据顺序相同。

这些格式是指定数据类型或格式的 Unicode 字符串，通常由 MIME 类型给出。一些非 MIME 类型的值是由于历史遗留原因（例如“text”）而特殊设置的。

语法
--
```

dataTransfer.types;
```

### 返回值

拖动操作中使用的数据格式数组。每种格式都是`字符串`类型。如果拖动操作不包含数据，则此数组列表将为空。如果拖动操作中包含任何文件，则其中一个类型将是 `Files`。

示例
--

这个例子展示 `types` 和 `items` 属性的用法

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

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

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

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

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

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

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

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.setData() - Web API 接口参考

DataTransfer.setData()
======================

**`DataTransfer.setData()`** 方法用来设置拖放操作的`drag data`到指定的数据和类型。

如果给定类型的数据不存在，则将其添加到拖动数据存储的末尾，使得 `types` 列表中的最后一个项目将是新类型。

如果给定类型的数据已经存在，现有数据将被替换为相同的位置。也就是说，替换相同类型的数据时 `types`列表的顺序不会更改。

示例数据类型为："`text/plain`" 和 "`text/uri-list`".

语法
--
```

void dataTransfer.setData(format, data);
```

### 参数

*format*

一个`DOMString` 表示要添加到 `drag object`的拖动数据的类型。

*data*

一个 `DOMString`表示要添加到 `drag object`的数据。

### 返回值

无

示例
--

此示例显示了使用 `DataTransfer` 对象的 `getData()`, `setData()` }和`clearData()` 方法。

```html
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>DataTransfer.setData()/.getData()/.clearData()</title>
    <style>
 div {
 margin: 0em;
 padding: 2em;
 }
 #source {
 color: blue;
 border: 1px solid black;
 }
 #target {
 border: 1px solid black;
 }
 </style>
  </head>
  <body>
    <section>
      <h1>
        <code>DataTransfer.setData()</code> <br />
        <code>DataTransfer.getData()</code> <br />
        <code>DataTransfer.clearData()</code>
      </h1>
      <div>
        <p id="source" ondragstart="dragstart\_handler(event);" draggable="true">
          Select this element, drag it to the Drop Zone and then release the
          selection to move the element.
        </p>
      </div>
      <div
 id="target"
 ondrop="drop\_handler(event);"
 ondragover="dragover\_handler(event);">
        Drop Zone
      </div>
    </section>
    <!-- js -->
    <script>
 function dragstart\_handler(ev) {
 console.log("dragStart");
 // Change the source element's background color to signify drag has started
 ev.currentTarget.style.border = "dashed";
 // Set the drag's format and data. Use the event target's id for the data
 ev.dataTransfer.setData("text/plain", ev.target.id);
 }

 function dragover\_handler(ev) {
 console.log("dragOver");
 // prevent Default event
 ev.preventDefault();
 }

 function drop\_handler(ev) {
 console.log("Drop");
 ev.preventDefault();
 // Get the data, which is the id of the drop target
 var data = ev.dataTransfer.getData("text");
 // appendChild
 ev.target.appendChild(document.getElementById(data));
 // Clear the drag data cache (for all formats/types)
 ev.dataTransfer.clearData();
 }
 </script>
  </body>
</html>
```

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.setDragImage() - Web API 接口参考

DataTransfer.setDragImage()
===========================

发生拖动时，从拖动目标 (`dragstart`事件触发的元素) 生成半透明图像，并在拖动过程中跟随鼠标指针。这个图片是自动创建的，你不需要自己去创建它。然而，如果想要设置为自定义图像，那么 **`DataTransfer.setDragImage()`** 方法就能派上用场。

图像通常是一个 `<image>` 元素，但也可以是`<canvas>` 或任何其他图像元素。该方法的 x 和 y 坐标是图像应该相对于鼠标指针出现的偏移量。

坐标指定鼠标指针相对于图片的偏移量。例如，要使图像居中，请使用图像宽度和高度的一半。

通常在 `dragstart` 事件处理程序中调用此方法。

语法
--
```

void dataTransfer.setDragImage(img, xOffset, yOffset);
```

### 参数

*img |* Element

用于拖曳反馈图像的图像 `Element` 元素。

如果 Element 是一个 img 元素，则将拖动位图设置为该元素的图像（保持大小）；否则，将拖动数位图设置为从给定元素所生成的图片（当前尚未指定执行此操作的确切机制）

*xOffset*

使用 `long` 指示相对于图片的横向偏移量

*yOffset*

使用 `long` 指示相对于图片的纵向偏移量

### 返回值

无

示例
--

这个例子展示如何使用 `setDragImage()` 方法。请注意，此例子引用了命名为 `example.gif` 的图片文件。如果此文件存在，它将被用作拖动图像，如果此文件不存在，浏览器会使用其默认的拖动图像。

```js
<!DOCTYPE html>
<html lang=en>
<title>Example of DataTransfer.setDragImage()</title>
<meta name="viewport" content="width=device-width">
<style>
  div {
    margin: 0em;
    padding: 2em;
  }
  #source {
    color: blue;
    border: 1px solid black;
  }
  #target {
    border: 1px solid black;
  }
</style>
<script>
function dragstart\_handler(ev) {
 console.log("dragStart");
 // 设置拖动的格式和数据。使用事件目标的 id 作为数据
 ev.dataTransfer.setData("text/plain", ev.target.id);
 // 创建一个图像并且使用它作为拖动图像
 // 请注意：改变 "example.gif" 为一个已经存在的图片
 // 或者，一个还没有创建出来的图片，那么浏览器将会使用默认的拖动图片
 // 译者注：默认的拖动图片与拖动对象没有联系。一般是一个小型文件图标
 var img = new Image();
 img.src = 'example.gif';
 ev.dataTransfer.setDragImage(img, 10, 10);
}

function dragover\_handler(ev) {
 console.log("dragOver");
 ev.preventDefault();
}

function drop\_handler(ev) {
 console.log("Drop");
 ev.preventDefault();
 // 获取拖放目标的 id 数据
 var data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
}
</script>
<body>
<h1>Example of <code>DataTransfer.setDragImage()</code></h1>
 <div>
   <p id="source" ondragstart="dragstart\_handler(event);" draggable="true">
     Select this element, drag it to the Drop Zone and then release the selection to move the element.</p>
 </div>
 <div id="target" ondrop="drop\_handler(event);" ondragover="dragover\_handler(event);">Drop Zone</div>
</body>
</html>
```

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.items - Web API 接口参考

DataTransfer.items
==================

`DataTransfer`的`items` 属性只读，是拖动操作中 `数据传输项`的`列表`。该列表包含了操作中每一项目的对应项，如果操作没有项目，则列表为空。

语法
--
```

itemList = dataTransfer.items;
```

### 返回值

一个`DataTransferItemList` 对象，包含了表示拖动操作中被拖动项的`DataTransferItem`对象，每一个拖动项对应一个列表项。如果拖动操作中没有数据，则列表为空。

示例
--

这个例子演示了 `items` 和 `types` 属性的用法。

```js
<!DOCTYPE html>
<html lang=en>
<title>Examples of DataTransfer.{types,items} properties</title>
<meta content="width=device-width">
<style>
  div {
    margin: 0em;
    padding: 2em;
  }
  #target {
    border: 1px solid black;
  }
</style>
<script>
function dragstart\_handler(ev) {
 console.log("dragStart: target.id = " + ev.target.id);
 // Add this element's id to the drag payload so the drop handler will
 // know which element to add to its tree
 ev.dataTransfer.setData("text/plain", ev.target.id);
 ev.dataTransfer.effectAllowed = "move";
}

function drop\_handler(ev) {
 console.log("drop: target.id = " + ev.target.id);
 ev.preventDefault();
 // Get the id of the target and add the moved element to the target's DOM
 var data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
 // Print each format type
 if (ev.dataTransfer.types != null) {
   for (var i=0; i < ev.dataTransfer.types.length; i++) {
     console.log("... types[" + i + "] = " + ev.dataTransfer.types[i]);
   }
 }
 // Print each item's "kind" and "type"
 if (ev.dataTransfer.items != null) {
   for (var i=0; i < ev.dataTransfer.items.length; i++) {
     console.log("... items[" + i + "].kind = " + ev.dataTransfer.items[i].kind + " ; type = " + ev.dataTransfer.items[i].type);
   }
 }
}

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

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.getData() - Web API 接口参考

DataTransfer.getData()
======================

**`DataTransfer.getData()`** 方法接受指定类型的拖放（以`DOMString`的形式）数据。如果拖放行为没有操作任何数据，会返回一个空字符串。

数据类型有：`text/plain`，`text/uri-list`。

语法
--
```

DOMString dataTransfer.getData(format);
```

### 参数

*format*

`DOMString`类型

### 返回值

`DOMString`

返回一个给定类型的`DOMString`格式的数据。如果没有操作数据或者没有指定操作数据的类型，都会返回一个空字符串。

### 注意

HTML5 拖放规范 规定了一个 `drag data store mode`。这可能会导致预期外的结果，即 **`DataTransfer.getData()`** 没有返回预期值。

示例
--

这个例子展示了 `DataTransfer`对象的`getData()`和`setData()`方法。

### HTML

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

### CSS

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

### JavaScript

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

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

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

### 结果

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.effectAllowed - Web API 接口参考

DataTransfer.effectAllowed
==========================

**`DataTransfer.effectAllowed`** 属性指定拖放操作所允许的一个效果。*copy* 操作用于指示被拖动的数据将从当前位置复制到放置位置。*move* 操作用于指定被拖动的数据将被移动。*link* 操作用于指示将在源和放置位置之间创建某种形式的关系或连接。

应该在`dragstart`事件中设置此属性，以便为拖动源设置所需的拖动效果。在 `dragenter` 和`dragover` 事件处理程序中，该属性将设置为在`dragstart` 事件期间分配的任何值，因此，可以使用`effectAllowed`来确定允许哪个效果。

给`effectAllowed`赋一个值，以使其在除`dragstart` 之外的事件中无效。

语法
--
```

dataTransfer.effectAllowed;
```

### 值

表示允许的拖动操作`DOMString` 。这个可能值是：

none

此项表示不允许放下

copy

源项目的复制项可能会出现在新位置。

copyLink

允许 *copy* 或者 *link* 操作。

copyMove

允许 *copy* 或者 *move* 操作。

link

可以在新地方建立与源的链接。

linkMove

允许 *link* 或者 *move* 操作。

move

一个项目可能被移动到新位置。

all

允许所有的操作。

uninitialized

效果没有设置时的默认值，则等同于 *all*。

分配一个没有效果的其他值给 `effectAllowed`，则保留原值。

Internet Explorer 会将该值改为小写。因此，`linkMove`将会变为 `linkmove`，等等。

示例
--

此例子展示 `effectAllowed` 用法 和 `dropEffect` 属性

```js
<!DOCTYPE html>
<html lang=en>
<title>Examples of DataTransfer.{dropEffect,effectAllowed} properties</title>
<meta content="width=device-width">
<style>
  div {
    margin: 0em;
    padding: 2em;
  }
  #source {
    color: blue;
    border: 1px solid black;
  }
  #target {
    border: 1px solid black;
  }
</style>
<script>
function dragstart\_handler(ev) {
 console.log("dragStart: dropEffect = " + ev.dataTransfer.dropEffect + " ; effectAllowed = " + ev.dataTransfer.effectAllowed);
 // 将这个元素的 id 添加到 drag 载荷中，
 // 以便 drop 事件知道将哪个元素添加到其树中。
 ev.dataTransfer.setData("text", ev.target.id);
 ev.dataTransfer.effectAllowed = "move";
}

function drop\_handler(ev) {
 console.log("drop: dropEffect = " + ev.dataTransfer.dropEffect + " ; effectAllowed = " + ev.dataTransfer.effectAllowed);
 ev.preventDefault();
 // 得到目标的 id 并且将移动的元素添加到目标 DOM 中
 var data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
}

function dragover\_handler(ev) {
 console.log("dragOver: dropEffect = " + ev.dataTransfer.dropEffect + " ; effectAllowed = " + ev.dataTransfer.effectAllowed);
 ev.preventDefault();
 // 设置 dropEffect 为 move
 ev.dataTransfer.dropEffect = "move"
}
</script>
<body>
<h1>Examples <code>DataTransfer</code>.{<code>dropEffect</code>, <code>effectAllowed</code>} properties</h1>
 <div>
   <p id="source" ondragstart="dragstart\_handler(event);" draggable="true">
     Select this element, drag it to the Drop Zone and then release the selection to move the element.</p>
 </div>
 <div id="target" ondrop="drop\_handler(event);" ondragover="dragover\_handler(event);">Drop Zone</div>
</body>
</html>
```

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐的拖拽类型
* DataTransfer 测试——粘贴或拖拽


DataTransfer.files - Web API 接口参考

DataTransfer.files
==================

\*\*`DataTransfer.files`\*\*属性在拖动操作中表示`文件列表`。如果操作不包含文件，则此列表为空。

此功能可用于将文件从用户桌面拖动到浏览器。

语法
--
```

dataTransfer.files;
```

### 返回值

拖动操作中的文件`列表`，操作中每个文件的一个列表项。如果拖动操作没有文件，此列表为空。

举个例子
----

这个接口有两个实例：

* 只针对 Firfox: http://jsfiddle.net/9C2EF/
* 所有浏览器：https://jsbin.com/hiqasek/
规范
--

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

浏览器兼容性
------

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


DataTransfer() - Web API 接口参考

DataTransfer()
==============

通过构造函数 **`DataTransfer`** 创建一个新的 `DataTransfer` 对象。注意，单独创建该对象没有意义，且 Internet Explorer 中 `DataTransfer` 不是一个构造函数。

语法
--
```

var dataTrans = new DataTransfer()
```

### 参数

无

### 返回值

一个空的 `DataTransfer` 对象。

规范
--

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

浏览器兼容性
------

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


DataTransfer.clearData() - Web API 接口参考

DataTransfer.clearData()
========================

**`DataTransfer.clearData()`** 方法删除给定类型的拖动操作的 `drag data`。如果给定类型的数据不存在，则此方法不执行任何操作。

如果调用此方法时没有传入参数，或者参数为空`字符串`，则将删除所有类型的数据。

此方法不会从拖动操作中删除文件，因此如果有任何文件包含在对象的 `DataTransfer.types` 列表中，仍然可能有一个类型为“Files”的条目在拖动。

**备注：** 该方法只能在 `dragstart` 事件的处理程序中使用，因为这是拖动操作的数据存储唯一能写入的时间。

语法
--

```js
DataTransfer.clearData([format]);
```

### 参数

`format` 可选

一个 `string` 指定要删除的数据类型。如果此参数为空字符串或未提供，则将删除所有类型的数据。

示例
--

这个例子显示了使用 `DataTransfer` 对象的 `getData()`、`setData()` 以及 `clearData()` 方法。

### HTML

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

### CSS

```css
span.tweaked {
  display: inline-block;
  margin: 1em 0;
  padding: 1em 2em;
}
#source {
  color: blue;
  border: 1px solid black;
}
#target {
  border: 1px solid black;
}
```

### JavaScript

```js
window.addEventListener("DOMContentLoaded", function () {
  // Select HTML elements
  var draggable = document.getElementById("source");
  var dropable = document.getElementById("target");
  var status = document.getElementById("status");
  var data = document.getElementById("data");
  var dropped = false;
  // Register event handlers
  draggable.addEventListener("dragstart", dragStartHandler);
  draggable.addEventListener("dragend", dragEndHandler);
  dropable.addEventListener("dragover", dragOverHandler);
  dropable.addEventListener("dragleave", dragLeaveHandler);
  dropable.addEventListener("drop", dropHandler);
  function dragStartHandler(event) {
    status.textContent = "Drag in process";
    // Change target element's border to signify drag has started
    event.currentTarget.style.border = "1px dashed blue";
    // Start by clearing existing clipboards; this will affect all types since we
    // don't give a specific type.
    event.dataTransfer.clearData();
    // Set the drag's format and data (use event target's id for data)
    event.dataTransfer.setData("text/plain", event.target.id);
    data.textContent = event.dataTransfer.getData("text/plain");
  }
  function dragEndHandler(event) {
    if (!dropped) {
      status.textContent = "Drag canceled";
    }
    data.textContent = event.dataTransfer.getData("text/plain") || "empty";
    // Change border to signify drag is no longer in process
    event.currentTarget.style.border = "1px solid black";
    if (dropped) {
      // Remove all event listeners
      draggable.removeEventListener("dragstart", dragStartHandler);
      draggable.removeEventListener("dragend", dragEndHandler);
      dropable.removeEventListener("dragover", dragOverHandler);
      dropable.removeEventListener("dragleave", dragLeaveHandler);
      dropable.removeEventListener("drop", dropHandler);
    }
  }
  function dragOverHandler(event) {
    status.textContent = "Drop available";
    event.preventDefault();
  }
  function dragLeaveHandler(event) {
    status.textContent = "Drag in process (drop was available)";
    event.preventDefault();
  }
  function dropHandler(event) {
    dropped = true;
    status.textContent = "Drop done";
    event.preventDefault();
    // Get data linked to event format « text »
    var _data = event.dataTransfer.getData("text/plain");
    var element = document.getElementById(_data);
    // Append drag source element to event's target element
    event.target.appendChild(element);
    // Change CSS styles and displayed text
    element.style.cssText =
      "border: 1px solid black;display: block; color: red";
    element.textContent = "I'm in the Drop Zone!";
  }
});
```

规范
--

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

浏览器兼容性
------

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

参见
--

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


DataTransfer.dropEffect - Web API 接口参考

DataTransfer.dropEffect
=======================

**`DataTransfer.dropEffect`** 属性控制在拖放操作中给用户的反馈（通常是视觉上的）。它会影响在拖拽过程中光标的手势。例如，当用户 hover 在一个放置目标元素上，浏览器的光标可能会预示了将会发生什么操作。

当 `DataTransfer` 被创建时，`dropEffect` 被设置为一个字符串。读这个值时会返回它的当前值。设置这个值时，如果这个新的值是下面列出的值中的一个，这个属性的值就会被设置为这个新的值，其他的值都会被忽略。

对于 `dragenter` 和 `dragover` 事件，`dropEffect` 会根据用户的请求的行为进行初始化。具体如何初始化和浏览器平台有关，但是通常来讲，用户可以通过按住修改键，比如 alt 键来修改想要的行为。当我们期望得到一个指定的行为时而不是用户的请求行为时，可以通过 `dragenter` 和 `dragover` 事件处理修改 `dropEffect` 的值。

对于 `drop` 和 `dragend` 事件，`dropEffect` 会被设置为想要得到的值，即最后一次 `dragenter` 或 `dragover` 事件后 `dropEffect` 的值。例如，在一个 `dragend` 事件中，如果期望得到的 dropEffect 是“move”，那么被拖拽的数据会从源中移除。

语法
--

```js
dataTransfer.dropEffect;
```

### 值

一个代表拖动操作效果的 `DOMString`，可能的值有：

`copy`

在新位置生成源项的副本

`move`

将项目移动到新位置

`link`

在新位置建立源项目的链接

`none`

项目可能禁止拖放（译者注：还与 effectAllowed 设置的值相关）

将任何其他值赋给 `dropEffect` 都没有效果，这种情况下会保留旧值。

示例
--

这个例子演示了 `dropEffect` 和 `effectAllowed` 属性的用法

### HTML

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

### CSS

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

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

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

### JavaScript

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

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

function drop\_handler(ev) {
  console.log(
    "drop: dropEffect = " +
      ev.dataTransfer.dropEffect +
      " ; effectAllowed = " +
      ev.dataTransfer.effectAllowed,
  );
  ev.preventDefault();

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

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

规范
--

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

浏览器兼容性
------

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

参见
--

* HTML 拖放 API
* 拖拽操作
* 推荐拖拽类型
* DataTransfer test - Paste or Drag


EyeDropper：open() 方法 - Web API 接口参考

EyeDropper：open() 方法
====================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`EyeDropper.open()`** 方法启动拾色器模式，返回一个 Promise，在用户选择颜色而退出拾色器模式后兑现。

语法
--

```js
open()
open(options)
```

### 参数

`options` 可选

一个用于传递 `AbortSignal` 信号的对象：

`signal`

一个 `AbortSignal` 对象。当调用 `AbortSignal` 的 `abort()` 方法时，拾色器模式将被中止。

### 返回值

一个 `Promise`，最终在用户从屏幕上选择一个像素颜色时解决。

该 Promise 会兑现一个带有以下属性的对象：

`sRGBHex`

代表所选颜色的字符串，采用十六进制 sRGB 格式（`#aabbcc`）。

### 异常

在 `Promise` 被拒绝（rejected）时，不会抛出异常，而是返回一个错误对象。Promise 在以下两种情况下被拒绝：

* 当用户通过按下 `Escape` 键来取消拾色器模式时。
* 当通过作为参数传递给 `open()` 方法的 `AbortController` 来中止拾色器模式时。
规范
--

| Specification |
| --- |
| EyeDropper API # dom-eyedropper-open |

浏览器兼容性
------

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

参见
--

* 它属于 `EyeDropper` 接口。


EyeDropper：EyeDropper() 构造函数 - Web API 接口参考

EyeDropper：EyeDropper() 构造函数
============================

**实验性:** **这是一项实验性技术**
在将其用于生产之前，请仔细检查浏览器兼容性表格。

**`EyeDropper()`** 构造函数返回一个新的 `EyeDropper` 对象。

语法
--

```js
new EyeDropper()
```

### 参数

无。

规范
--

| Specification |
| --- |
| EyeDropper API # eyedropper-interface |

浏览器兼容性
------

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

参见
--

* 它属于 `EyeDropper` 接口。