1. 6 用户交互
    1. 6.1 hidden 属性
    2. 6.2 页面可见性
      1. 6.2.1 VisibilityStateEntry 接口
    3. 6.3 非活动子树
      1. 6.3.1 模态对话框和非活动子树
      2. 6.3.2 inert 属性
    4. 6.4 跟踪用户激活
      1. 6.4.1 数据模型
      2. 6.4.2 处理模型
      3. 6.4.3 由用户激活控制的 API
      4. 6.4.4 UserActivation 接口
      5. 6.4.5 用户代理自动化
    5. 6.5 元素的激活行为
      1. 6.5.1 ToggleEvent 接口
    6. 6.6 焦点
      1. 6.6.1 简介
      2. 6.6.2 数据模型
      3. 6.6.3 tabindex 属性
      4. 6.6.4 处理模型
      5. 6.6.5 顺序焦点导航
      6. 6.6.6 焦点管理 API
      7. 6.6.7 autofocus 属性
    7. 6.7 分配键盘快捷键
      1. 6.7.1 简介
      2. 6.7.2 accesskey 属性
      3. 6.7.3 处理模型
    8. 6.8 编辑
      1. 6.8.1 使文档区域可编辑:contenteditable 内容属性
      2. 6.8.2 使整个文档可编辑:designMode 获取器和设置器
      3. 6.8.3 页面内编辑器的最佳实践
      4. 6.8.4 编辑 API
      5. 6.8.5 拼写和语法检查
      6. 6.8.6 写作建议
      7. 6.8.7 自动大写
      8. 6.8.8 自动更正
      9. 6.8.9 输入方式:inputmode 属性
      10. 6.8.10 输入方式:enterkeyhint 属性
    9. 6.9 页面内查找
      1. 6.9.1 简介
      2. 6.9.2detailshidden=until-found 的交互
      3. 6.9.3 与选择的交互
    10. 6.10 关闭请求和关闭观察器
      1. 6.10.1 关闭请求
      2. 6.10.2 关闭观察器基础设施
      3. 6.10.3 CloseWatcher 接口

6 用户交互

6.1 hidden 属性

Global_attributes/hidden

仅在一个引擎中支持。

Firefox不支持Safari不支持Chrome102+
Opera不支持Edge102+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

Global_attributes/hidden

在所有当前引擎中支持。

Firefox4+Safari5.1+Chrome10+
Opera?Edge79+
旧版 Edge12+Internet Explorer11
Firefox Android?Safari iOS?Chrome Android?WebView Android4+Samsung Internet?Opera Android?

所有 HTML 元素 都可以设置 hidden 内容属性。 hidden 属性是一个 枚举属性,具有以下关键字和状态

关键字状态简要描述
hidden hidden 不会被渲染。
(空字符串)
until-found 找到之前隐藏 不会被渲染,但内部内容对 页面内查找片段导航 可用。

该属性的 缺失值默认值未隐藏 状态,其 无效值默认值隐藏 状态。

当元素的 hidden 属性处于 隐藏 状态时,表示该元素尚未与页面的当前状态直接相关,或者不再直接相关,或者正在用于声明要由页面的其他部分重用的内容,而不是由用户直接访问。用户代理不应该渲染处于 隐藏 状态的元素。此要求可以通过样式层间接实现。例如,网页浏览器可以使用 渲染部分中建议的规则 来实现这些要求。

当元素的 hidden 属性处于 找到之前隐藏 状态时,表示该元素像处于 隐藏 状态一样隐藏,但元素内部的内容将对 页面内查找片段导航 可用。当这些功能试图滚动到元素子树中的目标时,用户代理将删除 hidden 属性以在滚动到目标之前显示内容。除了删除 hidden 属性外,还会在删除 hidden 属性之前在元素上触发名为 beforematch 的事件。

网页浏览器将在 hidden 属性处于 找到之前隐藏 状态时使用“content-visibility: hidden”而不是“display: none”,如 渲染部分 中所述。

由于此属性通常使用 CSS 实现,因此也可以使用 CSS 覆盖它。例如,应用“display: block”到所有元素的规则将取消 隐藏 状态的效果。因此,作者在编写样式表时必须注意,确保属性的样式仍然符合预期。此外,不支持 找到之前隐藏 状态的旧版用户代理将使用“display: none”而不是“content-visibility: hidden”,因此鼓励作者确保其样式表不会更改 找到之前隐藏 元素的“display”或“content-visibility”属性。

由于具有 hidden 属性且处于 找到之前隐藏 状态的元素使用“content-visibility: hidden”而不是“display: none”,因此 找到之前隐藏 状态有两个与 隐藏 状态不同的注意事项

  1. 元素需要受到 布局包含 的影响才能被页面内查找显示。这意味着,如果处于 找到之前隐藏 状态的元素的“display”值为“none”、“contents”或“inline”,则该元素将不会被页面内查找显示。

  2. 元素在处于 找到之前隐藏 状态时仍将具有 生成的框,这意味着元素周围的边框、边距和填充仍将被渲染。

在以下骨架示例中,该属性用于在用户登录之前隐藏网络游戏的首页

  <h1>The Example Game</h1>
  <section id="login">
   <h2>Login</h2>
   <form>
    ...
    <!-- calls login() once the user's credentials have been checked -->
   </form>
   <script>
    function login() {
      // switch screens
      document.getElementById('login').hidden = true;
      document.getElementById('game').hidden = false;
    }
   </script>
  </section>
  <section id="game" hidden>
   ...
  </section>

不应使用 hidden 属性隐藏本来可以在其他演示中显示的内容。例如,不应使用 hidden 来隐藏选项卡对话框中的面板,因为选项卡界面仅仅是一种溢出演示——同样也可以在带有滚动条的一个大页面中显示所有表单控件。同样,不应使用此属性仅从一个演示中隐藏内容——如果某些内容被标记为 hidden,则它将从所有演示中隐藏,包括屏幕阅读器等。

本身不 隐藏 的元素和脚本不应 超链接隐藏 的元素。本身不 隐藏labeloutput 元素的 for 属性同样不应引用 隐藏 的元素。在这两种情况下,此类引用都会导致用户混淆。

但是,元素和脚本可以在其他上下文中引用 隐藏 的元素。

例如,不应使用 href 属性链接到用 hidden 属性标记的部分。如果内容不适用或不相关,则没有理由链接到它。

但是,可以使用 ARIA aria-describedby 属性引用本身 隐藏 的描述。虽然隐藏描述意味着它们本身没有用,但可以以这样一种方式编写它们,即它们在被描述的元素引用的特定上下文中是有用的。

类似地,具有 hidden 属性的 canvas 元素可以被脚本化的图形引擎用作屏幕外缓冲区,并且表单控件可以使用其 form 属性引用隐藏的 form 元素。

hidden 属性隐藏的节区中的元素仍然是活动的,例如,此类节区中的脚本和表单控件仍然分别执行和提交。只有它们对用户的呈现发生了变化。

HTMLElement/hidden

在所有当前引擎中支持。

Firefox4+Safari5.1+Chrome6+
Opera11.6+Edge79+
旧版 Edge12+Internet Explorer11
Firefox Android?Safari iOS?Chrome Android?WebView Android3+Samsung Internet?Opera Android12+

The hidden getter steps are

  1. 如果 hidden 属性处于 隐藏直到找到 状态,则返回 "until-found"。

  2. 如果 hidden 属性已设置,则返回 true。

  3. 返回 false。

The hidden setter steps are

  1. 如果给定值为一个字符串,并且该字符串与 "until-found" 不区分大小写 的 ASCII 匹配,则将 hidden 属性设置为 "until-found"。

  2. 否则,如果给定值为 false,则删除 hidden 属性。

  3. 否则,如果给定值为一个空字符串,则删除 hidden 属性。

  4. 否则,如果给定值为 null,则删除 hidden 属性。

  5. 否则,如果给定值为 0,则删除 hidden 属性。

  6. 否则,如果给定值为 NaN,则删除 hidden 属性。

  7. 否则,将 hidden 属性设置为一个空字符串。

The ancestor hidden-until-found revealing algorithm is to run the following steps on currentNode

  1. currentNode扁平树 中有一个父节点时

    1. 如果 currentNode隐藏直到找到 状态中具有 hidden 属性,则

      1. 触发 一个名为 beforematch 的事件,该事件在 currentNode 上。

      2. currentNode 中删除 hidden 属性。

    2. currentNode 设置为 currentNode扁平树 中的父节点。

6.2 页面可见性

一个 可遍历可导航系统可见性状态,包括其创建时的初始值,由用户代理决定。例如,它表示浏览器窗口是否已最小化,浏览器标签页当前是否处于后台,或者任务切换器等系统元素是否遮挡了页面。

当用户代理确定 可遍历可导航 traversable系统可见性状态 已更改为 newState 时,它必须运行以下步骤

  1. navigablestraversable活动文档包含后代可导航

  2. 对于 navigables 中的每个 navigable 按什么顺序?

    1. documentnavigable活动文档

    2. 将一个全局任务排队 到由 document相关全局对象 给定的 用户交互任务源 上,以 更新 document 的可见性状态,并使用 newState

一个 Document 具有 可见性状态,它可以是 "hidden" 或 "visible",最初设置为 "hidden"。

Document/visibilityState

在所有当前引擎中支持。

Firefox18+Safari7+Chrome33+
Opera20+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS?Chrome Android?WebView Android4.4.3+Samsung Internet?Opera Android20+

The visibilityState getter steps are to return this's visibility state.

Document/hidden

在所有当前引擎中支持。

Firefox18+Safari7+Chrome33+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer10+
Firefox Android?Safari iOS?Chrome Android?WebView Android4.4.3+Samsung Internet?Opera Android12.1+

The hidden getter steps are to return true if this's visibility state is "hidden", otherwise false.

To update the visibility state of Document document to visibilityState

  1. 如果 document可见性状态 等于 visibilityState,则返回。

  2. document可见性状态 设置为 visibilityState

  3. 排队 一个新的 VisibilityStateEntry,其 可见性状态visibilityState,其 时间戳 为由 document相关全局对象 给定的 当前高分辨率时间

  4. 使用 document 运行 屏幕方向更改步骤[SCREENORIENTATION]

  5. 使用 document 运行 视图转换页面可见性更改步骤

  6. 运行任何 页面可见性更改步骤,这些步骤可能在其他规范中定义,并使用 可见性状态document

    如果规范作者直接发送拉取请求以从这里添加调用到他们的规范中,而不是使用 页面可见性更改步骤 挂钩,这会更好,以确保定义明确的跨规范调用顺序。截至撰写本文时,以下规范已知具有 页面可见性更改步骤,这些步骤将按未指定的顺序运行:设备姿势 APIWeb NFC[DEVICEPOSTURE] [WEBNFC]

  7. document 上触发一个名为 visibilitychange 的事件,其 bubbles 属性初始化为 true。

6.2.1 The VisibilityStateEntry interface

VisibilityStateEntry

仅在一个引擎中支持。

FirefoxNoSafariNoChrome115+
Opera?Edge115+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

The VisibilityStateEntry interface exposes visibility changes to the document, from the moment the document becomes active.

For example, this allows JavaScript code in the page to examine correlation between visibility changes and paint timing
function wasHiddenBeforeFirstContentfulPaint() {
    const fcpEntry = performance.getEntriesByName("first-contentful-paint")[0];
    const visibilityStateEntries = performance.getEntriesByType("visibility-state");
    return visibilityStateEntries.some(e =>
                                            e.startTime < fcpEntry.startTime &&
                                            e.name === "hidden");
}

Since hiding a page can cause throttling of rendering and other user-agent operations, it is common to use visibility changes as an indication that such throttling has occurred. However, other things could also cause throttling in different browsers, such as long periods of inactivity.

[Exposed=(Window)]
interface VisibilityStateEntry : PerformanceEntry {
  readonly attribute DOMString name;                 // shadows inherited name
  readonly attribute DOMString entryType;            // shadows inherited entryType
  readonly attribute DOMHighResTimeStamp startTime;  // shadows inherited startTime
  readonly attribute unsigned long duration;         // shadows inherited duration
};

The VisibilityStateEntry has an associated DOMHighResTimeStamp timestamp.

The VisibilityStateEntry has an associated "visible" or "hidden" visibility state.

The name getter steps are to return this's visibility state.

The entryType getter steps are to return "visibility-state".

The startTime getter steps are to return this's timestamp.

The duration getter steps are to return zero.

6.3 Inert 子树

另请参阅 inert 以了解同名属性的解释。

节点(特别是元素和文本节点)可以是 inert。当一个节点是 inert

惰性节点通常无法获得焦点,并且用户代理不会将惰性节点暴露给辅助功能 API 或辅助技术。作为命令的惰性节点将变得对用户不可操作,方式如上所述。

然而,用户代理可能允许用户覆盖对页面内查找和文本选择的限制。

默认情况下,节点不是惰性的

一个Document document 如果subjectdocument中处于最顶层的dialog 元素,则会被模态对话框 subject 阻塞。当document被阻塞时,所有连接到document的节点,除了subject 元素及其扁平树 后代,都必须变得惰性

subject还可以通过inert 属性变得惰性,但这仅限于在subject 本身指定的情况(即subject 逃脱了祖先的惰性);subject扁平树 后代可以通过类似的方式变得惰性

dialog 元素的showModal() 方法通过添加 dialog 元素到其节点文档顶层 来触发此机制。

6.3.2 inert 属性

Global_attributes/inert

在所有当前引擎中支持。

Firefox112+Safari15.5+Chrome102+
Opera?Edge102+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

inert 属性是一个布尔属性,通过其存在来表明该元素及其扁平树 后代(不包括逃脱惰性的元素,例如模态对话框)应该被用户代理设置为惰性

惰性子树不应包含任何对理解或使用页面中非惰性部分至关重要的内容或控件。惰性子树中的内容不会被所有用户感知或交互。作者不应将元素指定为惰性,除非它们所代表的内容也以某种方式被视觉遮挡。在大多数情况下,作者不应在单个表单控件上指定inert 属性。在这些情况下,disabled 属性可能更合适。

以下示例展示了如何将部分加载的内容标记为惰性,这些内容被“加载中”消息视觉遮挡。

<section aria-labelledby=s1>
  <h3 id=s1>Population by City</h3>
  <div class=container>
    <div class=loading><p>Loading...</p></div>
    <div inert>
      <form>
        <fieldset>
          <legend>Date range</legend>
          <div>
            <label for=start>Start</label>
            <input type=date id=start>
          </div>
          <div>
            <label for=end>End</label>
            <input type=date id=end>
          </div>
          <div>
            <button>Apply</button>
          </div>
        </fieldset>
      </form>
      <table>
        <caption>From 20-- to 20--</caption>
        <thead>
          <tr>
            <th>City</th>
            <th>State</th>
            <th>20-- Population</th>
            <th>20-- Population</th>
            <th>Percentage change</th>
          </tr>
        </thead>
        <tbody>
          <!-- ... -->
        </tbody>
      </table>
    </div>
  </div>
</section>
Screenshot of Population by City content with an overlaid loading message which visually obscures the form controls and data table which have not fully rendered, and thus are in the inert state.

“加载中”覆盖层遮挡了惰性内容,使其视觉上显而易见,惰性内容目前不可访问。请注意,标题和“加载中”文本不是带有inert 属性的元素的后代。这将确保此文本对所有用户可访问,而惰性内容无法被任何人交互。

默认情况下,没有持久性的视觉指示表明元素或其子树是惰性的。此类内容的适当视觉样式通常取决于上下文。例如,一个惰性屏幕外导航面板不需要默认样式,因为其屏幕外位置会视觉遮挡内容。类似地,模态dialog 元素的背景将用作视觉遮挡网页惰性内容的方式,而不是专门为惰性内容设置样式。

然而,对于许多其他情况,强烈鼓励作者明确标记文档的哪些部分是活动的,哪些是惰性的,以避免用户困惑。特别是,值得记住的是,并非所有用户都能同时看到页面的所有部分;例如,屏幕阅读器用户、小型设备或放大镜用户,甚至使用特别小窗口的用户可能无法看到页面的活动部分,如果惰性部分没有明显是惰性的,他们可能会感到沮丧。

HTMLElement/inert

在所有当前引擎中支持。

Firefox112+Safari15.5+Chrome102+
Opera?Edge102+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

inert IDL 属性必须反映同名内容属性。

6.4 跟踪用户激活

为了防止滥用某些 API,这些 API 可能对用户造成困扰(例如,打开弹出窗口或振动手机),用户代理仅允许在用户主动与网页交互或至少与页面交互过一次时使用这些 API。这种“主动交互”状态通过本节中定义的机制维护。

6.4.1 数据模型

为了跟踪用户激活,每个Window W 都有两个相关值

用户代理还定义了一个瞬时激活持续时间,这是一个常数,表示用户激活对于某些用户激活门控 API(例如,打开弹出窗口)可用多长时间。

瞬时激活持续时间 预计最多几秒钟,以便用户可以感知到页面交互与页面调用激活门控 API 之间的联系。

然后我们有以下W 的布尔用户激活状态

粘性激活

当给定W当前高分辨率时间 大于或等于W 中的最后激活时间戳 时,则称W 具有粘性激活

这是W 的历史激活状态,表示用户是否曾在W 中交互过。它最初为假,然后在W 收到第一个激活通知 时变为真(并且永远不会再变回假)。

瞬时激活

当给定W当前高分辨率时间 大于或等于W 中的最后激活时间戳,并且小于W 中的最后激活时间戳 加上瞬时激活持续时间 时,则称W 具有瞬时激活

这是W 的当前激活状态,表示用户是否最近在W 中交互过。它最初为假,并且在W 收到每个激活通知 后,在有限的时间内保持为真。

如果瞬时激活 状态变为假,因为自上次用户激活以来已经过去了瞬时激活持续时间,则该状态被认为是过期。请注意,它可以通过激活消耗 甚至在过期时间之前变为假。

历史操作激活

W最后历史操作激活时间戳 不等于W最后激活时间戳 时,则称W 具有历史操作激活

这是用户激活的一种特殊变体,用于允许访问某些会话历史 API,如果这些 API 使用得太频繁,会使用户难以使用浏览器 UI 返回。它最初为假,并且在用户与W 交互时变为真,但通过历史操作激活消耗 重置为假。这确保了这些 API 无法在没有中间用户激活的情况下连续使用多次。但与瞬时激活 不同,没有时间限制,这些 API 在此时间限制内必须使用。

即使在 文档 改变其 完全活动 状态后(例如,在从 文档 导航离开后,或导航到缓存的 文档 后),上次激活时间戳上次历史操作激活时间戳 仍然会保留。这意味着 粘性激活 状态跨越多个导航,只要使用相同的 文档。对于短暂激活状态,原始的 过期 时间保持不变(即,状态仍然在从原始的 激活触发输入事件 开始的 短暂激活持续时间 限制内过期)。在决定是否将某些东西基于 粘性激活短暂激活 时,务必考虑这一点。

6.4.2 处理模型

当用户交互导致在 文档 document 中触发 激活触发输入事件 时,用户代理必须在 分派 事件之前执行以下 激活通知 步骤

  1. 断言document完全活动 的。

  2. windows 为 « document相关全局对象 »。

  3. 扩展 windows,其中包含 document 的每个 祖先可导航元素活动窗口

  4. 扩展 windows,其中包含 document 的每个 后代可导航元素活动窗口,过滤后的列表只包含那些 可导航元素,这些元素的 活动文档来源document来源 同源

  5. 对于 windows 中的每个 window

    1. window上次激活时间戳 设置为 当前高分辨率时间

    2. 通知关闭观察器管理器关于用户激活,给出 window

一个 激活触发输入事件 是任何事件,其 isTrusted 属性为 true,且其 type 是以下之一

激活消耗 API 在本规范和其他规范中定义,可以通过执行以下步骤来 消耗用户激活,给出 窗口 W

  1. 如果 W可导航元素 为 null,则返回。

  2. topW可导航元素顶层可遍历元素

  3. navigablestop活动文档包含后代可导航元素

  4. windows 为通过获取 navigables 中每个项目 活动窗口 构造的 窗口 对象列表。

  5. 对于 windows 中的每个 window,如果 window上次激活时间戳 不是正无穷大,则将 window上次激活时间戳 设置为负无穷大。

历史操作激活消耗 API 可以通过执行以下步骤来 消耗历史操作用户激活,给出 窗口 W

  1. 如果 W可导航元素 为 null,则返回。

  2. topW可导航元素顶层可遍历元素

  3. navigablestop活动文档包含后代可导航元素

  4. windows 为通过获取 navigables 中每个项目 活动窗口 构造的 窗口 对象列表。

  5. 对于 windows 中的每个 window,将 window上次历史操作激活时间戳 设置为 window上次激活时间戳

请注意,页面中受 激活通知激活消耗 影响的 浏览上下文 集合之间的不对称性:激活消耗会将页面中所有浏览上下文的 短暂激活 状态更改为 false,而激活通知只会将这些浏览上下文中的一个子集的状态更改为 true。消耗的这种详尽性是故意的:它阻止了恶意网站从单个用户激活(可能通过利用 iframe 的深层层次结构)对 激活消耗 API 进行多次调用。

6.4.3 受用户激活限制的 API

依赖用户激活的 API 分为不同的级别

粘性激活限制的 API

这些 API 要求 粘性激活 状态为 true,因此它们会在第一次用户激活之前被阻止。

短暂激活限制的 API

这些 API 要求 短暂激活 状态为 true,但它们不会 消耗 它,因此在短暂状态 过期 之前,每个用户激活都可以进行多次调用。

短暂激活消耗 API

这些 API 要求 短暂激活 状态为 true,并且它们在每次调用中都会 消耗用户激活,以防止每个用户激活进行多次调用。

历史操作激活消耗 API

这些 API 要求 历史操作激活 状态为 true,并且它们在每次调用中都会 消耗历史操作用户激活,以防止每个用户激活进行多次调用。

6.4.4 UserActivation 接口

UserActivation

FirefoxSafari16.4+Chrome72+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

每个 窗口 都有一个 关联的 UserActivation,它是一个 UserActivation 对象。在创建 窗口 对象时,其 关联的 UserActivation 必须设置为在 窗口 对象的 相关领域 中创建的 新的 UserActivation 对象。

[Exposed=Window]
interface UserActivation {
  readonly attribute boolean hasBeenActive;
  readonly attribute boolean isActive;
};

partial interface Navigator {
  [SameObject] readonly attribute UserActivation userActivation;
};
navigator.userActivation.hasBeenActive

返回窗口是否具有粘性激活

navigator.userActivation.isActive

返回窗口是否具有瞬时激活

Navigator/userActivation

FirefoxSafari16.4+Chrome72+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

The userActivation getter steps are to return this's 相关全局对象's 关联的UserActivation.

UserActivation/hasBeenActive

FirefoxSafari16.4+Chrome72+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

The hasBeenActive getter steps are to return true if this's 相关全局对象 has 粘性激活, and false otherwise.

UserActivation/hasBeenActive

FirefoxSafari16.4+Chrome72+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

The isActive getter steps are to return true if this's 相关全局对象 has 瞬时激活, and false otherwise.

6.4.5 User agent automation

为了用户代理自动化和应用程序测试的目的,本规范定义了以下扩展命令 用于 Web Driver 规范。用户代理可以选择是否支持以下扩展命令[WEBDRIVER]

HTTP 方法URI 模板
`POST`/session/{session id}/window/consume-user-activation

The 远程端步骤

  1. window当前浏览上下文's 活动窗口.

  2. consume 为 true 如果 window 具有瞬时激活;否则为 false。

  3. 如果 consume 为 true,则消耗用户激活 window.

  4. 返回 success 与数据 consume.

6.5 元素的激活行为

HTML 中的某些元素具有激活行为,这意味着用户可以激活它们。这总是由 click 事件引起的。

用户代理应允许用户手动触发具有激活行为的元素,例如使用键盘或语音输入,或通过鼠标点击。当用户以点击以外的方式触发具有定义的激活行为的元素时,交互事件的默认操作必须是 在元素上触发一个click 事件

element.click()

HTMLElement/click

在所有当前引擎中支持。

Firefox3+Safari6+Chrome9+
Opera10.5+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android4+Safari iOS?Chrome Android?WebView Android4.4+Samsung Internet1.0+Opera Android11+

模拟元素被点击。

每个元素都有一个关联的点击进行中标志,最初未设置。

The click() 方法必须执行以下步骤

  1. 如果此元素是禁用的表单控件,则返回。

  2. 如果此元素的点击进行中标志 已设置,则返回。

  3. 设置此元素的点击进行中标志

  4. 触发一个名为 click 的合成指针事件,在该元素上,并将不信任标志 设置为已设置。

  5. 取消设置此元素的点击进行中标志

6.5.1 The ToggleEvent interface

ToggleEvent/ToggleEvent

在所有当前引擎中支持。

Firefox🔰 114+Safari17+Chrome114+
Opera?Edge114+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

ToggleEvent

在所有当前引擎中支持。

Firefox🔰 114+Safari17+Chrome114+
Opera?Edge114+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?
[Exposed=Window]
interface ToggleEvent : Event {
  constructor(DOMString type, optional ToggleEventInit eventInitDict = {});
  readonly attribute DOMString oldState;
  readonly attribute DOMString newState;
};

dictionary ToggleEventInit : EventInit {
  DOMString oldState = "";
  DOMString newState = "";
};
event.oldState

从关闭转换为打开时设置为"closed",或从打开转换为关闭时设置为"open"。

event.newState

从关闭转换为打开时设置为"open",或从打开转换为关闭时设置为"closed"。

ToggleEvent/oldState

在所有当前引擎中支持。

Firefox🔰 114+Safari17+Chrome114+
Opera?Edge114+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

ToggleEvent/newState

在所有当前引擎中支持。

Firefox🔰 114+Safari17+Chrome114+
Opera?Edge114+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

The oldState and newState attributes must return the values they are initialized to.

A 切换任务跟踪器 是一个结构体,它具有

任务
一个任务,它触发ToggleEvent
旧状态
一个字符串,表示任务 事件的值,用于oldState 属性。

6.6 焦点

6.6.1 简介

本节为非规范性内容。

HTML 用户界面通常包含多个交互式小部件,例如表单控件、可滚动区域、链接、对话框、浏览器标签等。这些小部件构成一个层次结构,其中一些(例如浏览器标签、对话框)包含其他(例如链接、表单控件)。

使用键盘与界面交互时,键盘输入会从系统通过交互式小部件的层次结构传送到活动小部件,该小部件被称为获得焦点

考虑一个在图形环境中运行的浏览器标签中运行的 HTML 应用程序。假设此应用程序有一个包含一些文本控件和链接的页面,并且当前正在显示一个模态对话框,该对话框本身有一个文本控件和一个按钮。

在此场景中,可聚焦小部件的层次结构将包括浏览器窗口,该窗口在其子级中将具有包含 HTML 应用程序的浏览器标签。标签本身将具有其子级中的各种链接和文本控件,以及对话框。对话框本身将具有其子级中的文本控件和按钮。

如果在此示例中具有焦点的小部件是对话框中的文本控件,则键盘输入将从图形系统传送到① 网页浏览器,然后传送到② 标签,然后传送到③ 对话框,最后传送到④ 文本控件。

键盘事件始终针对此获得焦点的元素。

6.6.2 数据模型

A 顶级可遍历 具有系统焦点 当它可以接收从操作系统传来的键盘输入时,该输入可能针对其活动文档后代可遍历 中的一个。

A 顶级可遍历 具有用户注意力 当其系统可见性状态 为"visible",并且它要么具有系统焦点,要么与之直接相关的用户代理小部件可以接收从操作系统传来的键盘输入。

当浏览器窗口失去焦点时,用户注意力就会丢失,而系统焦点也可能会丢失给浏览器窗口中的其他系统小部件,例如地址栏。

A Document d 是一个具有用户注意力的顶级可遍历的完全活动后代d完全活动 并且 d节点可遍历顶级可遍历 具有用户注意力

术语可聚焦区域 用于指代界面中可以进一步成为此类键盘输入目标的区域。可聚焦区域可以是元素、元素的一部分或用户代理管理的其他区域。

每个可聚焦区域 都有一个DOM 锚点,它是一个Node 对象,表示可聚焦区域 在 DOM 中的位置。(当可聚焦区域 本身是一个Node 时,它就是它自己的DOM 锚点。)DOM 锚点 在某些 API 中用作可聚焦区域 的替代品,当没有其他 DOM 对象来表示可聚焦区域 时。

下表描述了哪些对象可以是可聚焦区域。左列中的单元格描述了可以是可聚焦区域 的对象;右列中的单元格描述了这些元素的DOM 锚点。(跨越两列的单元格是非规范性示例。)

可聚焦区域 DOM 锚点
示例
满足以下所有条件的元素 元素本身。

iframedialog<input type=text>,有时<a href="">(取决于平台约定)。

img元素关联的图像地图area元素的形状,该img元素正在渲染且不是惰性The img element.

在以下示例中,area元素在每个图像上创建两个形状。第一个形状的DOM锚是第一个img元素,第二个形状的DOM锚是第二个img元素。

<map id=wallmap><area alt="Enter Door" coords="10,10,100,200" href="door.html"></map>
...
<img src="images/innerwall.jpeg" alt="There is a white wall here, with a door." usemap="#wallmap">
...
<img src="images/outerwall.jpeg" alt="There is a red wall here, with a door." usemap="#wallmap">
正在渲染且不是实际禁用惰性的元素的用户代理提供的子部件。可聚焦区域是子部件的元素。

video元素的用户界面中的控件,旋转控件版本<input type=number>中的向上和向下按钮,details元素渲染中使用键盘输入打开或关闭元素的部分。

正在渲染且不是惰性的元素的可滚动区域。创建可滚动区域滚动的框的元素。

CSS 'overflow' 属性的'scroll'值通常会创建一个可滚动区域。

具有非空浏览上下文且不是惰性Document视窗创建视窗Document

iframe的内容。

用户代理确定的任何其他元素或元素部分,作为可聚焦区域,尤其是为了辅助无障碍或更好地匹配平台约定。元素。

用户代理可以使所有列表项项目符号顺序可聚焦,以便用户可以更轻松地浏览列表。

类似地,用户代理可以使所有具有title属性的元素顺序可聚焦,以便可以访问其建议信息。

可导航容器(例如,iframe)是一个可聚焦区域,但是路由到可导航容器的键事件会立即路由到其内容可导航活动文档。类似地,在顺序焦点导航中,可导航容器实际上只是其内容可导航活动文档的占位符。


每个Document中一个可聚焦区域被指定为文档的焦点区域。根据本规范中的算法,哪个控件被指定会随着时间的推移而改变。

即使文档不是完全活动且未显示给用户,它仍然可以具有文档的焦点区域。如果文档的完全活动状态发生变化,则其文档的焦点区域将保持不变。

The currently focused area of a top-level traversable traversable is the focusable area-or-null returned by this algorithm

  1. 如果traversable没有系统焦点,则返回null。

  2. candidatetraversable活动文档

  3. candidate焦点区域是具有非空内容可导航可导航容器时:将candidate设置为该可导航容器内容可导航活动文档

  4. 如果candidate焦点区域为非空,则将candidate设置为candidate焦点区域

  5. Return candidate.

The current focus chain of a top-level traversable traversable is the focus chain of the currently focused area of traversable, if traversable is non-null, or an empty list otherwise.

作为可聚焦区域DOM锚的元素被称为获得焦点,当该可聚焦区域成为顶级可遍历的当前焦点区域时。当元素是顶级可遍历的当前焦点区域可聚焦区域DOM锚时,它就是聚焦的。

The focus chain of a focusable area subject is the ordered list constructed as follows

  1. output为空列表

  2. currentObjectsubject

  3. 当为真时

    1. 追加currentObjectoutput

    2. 如果currentObjectarea元素的形状,则追加area元素到output

      否则,如果currentObjectDOM锚是与currentObject本身不同的元素,则追加currentObjectDOM锚output

    3. 如果currentObject可聚焦区域,则将currentObject设置为currentObjectDOM锚节点文档

      否则,如果currentObjectDocument,其节点可导航父级为非空,则将currentObject设置为currentObject节点可导航父级

      否则,中断

  4. Return output.

    链从subject开始,并且(如果subject是或可以是顶级可遍历的当前焦点区域)继续向上沿着焦点层次结构直到顶级可遍历Document

所有作为可聚焦区域的元素都被认为是可聚焦的。

对于可聚焦区域,存在两种特殊类型的可聚焦性

不是可聚焦的元素不是可聚焦区域,因此不是顺序可聚焦的,也不是单击可聚焦的。

是否为可 获取焦点 的元素,指的是该元素是否可以通过编程方式获得焦点,例如通过 focus() 方法或 autofocus 属性。相比之下,顺序可获取焦点点击可获取焦点 则控制用户代理对用户交互的响应方式:分别对应 顺序焦点导航激活行为

用户代理可能会根据用户偏好,即使元素是 可获取焦点 的,并且包含在其 文档顺序焦点导航顺序 中,也会判定它不是 顺序可获取焦点 的。例如,macOS 用户可以将用户代理设置为跳过非表单控件元素,或在仅使用 Tab 键 (而不是使用 OptionTab 键组合) 进行 顺序焦点导航 时跳过链接。

类似地,用户代理可能会判定元素即使是 可获取焦点 的,也不是 点击可获取焦点 的。例如,在某些用户代理中,单击不可编辑的表单控件不会使它获得焦点,即用户代理已判定此类控件不是点击可获取焦点。

因此,元素可以是 可获取焦点 的,但既不是 顺序可获取焦点 的,也不是 点击可获取焦点 的。例如,在某些用户代理中,具有负整数 tabindex 值 的不可编辑表单控件无法通过用户交互获得焦点,只能通过编程 API 获得焦点。

当用户 激活 一个 点击可获取焦点可获取焦点区域 时,用户代理必须在该 可获取焦点区域 上运行 获取焦点步骤,并将 焦点触发器 设置为 "click"。

请注意,获取焦点不是 激活行为,即在元素上调用 click() 方法或在元素上分派合成 click 事件不会导致该元素获得焦点。


如果节点是 文档影子宿主插槽 或处于 弹出状态 并且还设置了 弹出调用者 的元素,则它就是一个 焦点导航范围所有者

每个 焦点导航范围所有者 都有一个 焦点导航范围,它是一个元素列表。其内容由以下方式确定:

每个元素 element 都有一个 关联的焦点导航所有者,它可以是 null 或 焦点导航范围所有者。它由以下算法确定:

  1. 如果 element 的父级为 null,则返回 null。

  2. 如果 element 的父级是 影子宿主,则返回 element已分配的插槽

  3. 如果 element 的父级是 影子根,则返回父级的 宿主

  4. 如果 element 的父级是 文档元素,则返回父级的 节点文档

  5. 如果 element 处于 弹出状态 并且设置了 弹出调用者,则返回 element

  6. 返回 element 父级的 关联的焦点导航所有者

然后,给定 焦点导航范围所有者 owner焦点导航范围 的内容是所有 关联的焦点导航所有者owner 的元素。

元素在 焦点导航范围 内的顺序不会影响本规范中的任何算法。排序只在下面定义的 tabindex 排序焦点导航范围扁平化的 tabindex 排序焦点导航范围 概念中变得重要。

一个 tabindex 排序焦点导航范围 是一个 可获取焦点区域焦点导航范围所有者 的列表。每个 焦点导航范围所有者 owner 都有 tabindex 排序焦点导航范围,其内容由以下方式确定:

tabindex 排序焦点导航范围 内的顺序由每个元素的 tabindex 值 确定,如下面部分所述。

这些规则并没有给出精确的排序,因为它们主要由 "应该" 语句和相对排序组成。

一个 扁平化的 tabindex 排序焦点导航范围 是一个 可获取焦点区域 的列表。每个 焦点导航范围所有者 owner 拥有一个独特的 扁平化的 tabindex 排序焦点导航范围,其内容由以下算法确定:

  1. resultownertabindex 排序焦点导航范围克隆

  2. 对于 result 的每个 item

    1. 如果 item 不是 焦点导航范围所有者,则 继续

    2. 如果 item 不是 可获取焦点区域,则将 item 替换为 item扁平化的 tabindex 排序焦点导航范围 中的所有项目。

    3. 否则,将 item扁平化的 tabindex 排序焦点导航范围 的内容插入到 item 之后。

6.6.3 tabindex 属性

Global_attributes/tabindex

在所有当前引擎中支持。

Firefox1.5+Safari4+Chrome1+
Opera?Edge79+
Edge (Legacy)12+Internet ExplorerYes
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

tabindex 内容属性 允许作者使元素及其具有该元素作为其 DOM 锚点 的区域成为 可获取焦点区域,允许或阻止它们成为 顺序可获取焦点 的,并为 顺序焦点导航 确定它们的相对顺序。

"tabindex" 这个名字来自 Tab 键常用以在可获取焦点的元素之间导航。术语 "tabbing" 指的是向前移动到 顺序可获取焦点可获取焦点区域

如果指定了 tabindex 属性,则它必须具有一个 有效的整数 值。正数指定元素的 可获取焦点区域顺序焦点导航顺序 中的相对位置,而负数表示该控件不是 顺序可获取焦点 的。

开发人员在使用除 0 或 -1 以外的值作为其 tabindex 属性时应谨慎,因为这样做很难做到正确。

以下内容提供了可能 tabindex 属性值的非规范性摘要。下面的处理模型给出了更精确的规则。

省略 (或非整数的值)
用户代理将决定元素是否为 可获取焦点 的,如果是,则决定它是否为 顺序可获取焦点 的或 点击可获取焦点 的 (或两者都是)。
-1 (或其他负整数的值)
使元素成为 可获取焦点 的,并表示作者希望该元素为 点击可获取焦点 的,但不是 顺序可获取焦点 的。用户代理可能会忽略这种对于点击和顺序可获取焦点的偏好,例如,对于特定元素类型,根据平台约定,或对于仅使用键盘的用户。
0
使元素成为 可获取焦点 的,并表示作者希望该元素既是 点击可获取焦点 的,又是 顺序可获取焦点 的。用户代理可能会忽略这种对于点击和顺序可获取焦点的偏好。
正整数的值
与 0 的行为相同,但此外还在 tabindex 排序焦点导航范围 内创建一个相对顺序,因此 tabindex 属性值更高的元素出现在后面。

请注意,tabindex 属性不能用来使元素不可获取焦点。页面作者使元素不可获取焦点的唯一方法是 禁用 该元素,或使它 不活动


元素的tabindex 值 是其tabindex 属性的值,使用解析整数的规则进行解析。如果解析失败或未指定属性,则tabindex 值 为空。

的可聚焦区域的tabindex 值 是其DOM 锚点tabindex 值

必须按以下方式解释元素的tabindex 值

如果值为 null

用户代理应遵循平台约定来确定是否应将元素视为可聚焦区域,如果是,则元素及其可聚焦区域(以元素作为其DOM 锚点)是否可顺序聚焦,如果是,则其在tabindex 顺序焦点导航范围中的相对位置是什么。如果元素是焦点导航范围所有者,则必须将其包含在其tabindex 顺序焦点导航范围中,即使它不是可聚焦区域

对于属于同一焦点导航范围tabindex 值 为空的元素和可聚焦区域,它们在tabindex 顺序焦点导航范围内的相对排序应按影子包含树的顺序进行。

除平台约定外,建议将以下元素视为可聚焦区域可顺序聚焦

如果值为负整数

用户代理必须将元素视为可聚焦区域,但应将元素从任何tabindex 顺序焦点导航范围中省略。

忽略顺序焦点导航不允许作者导致元素的唯一有效原因是,如果用户移动焦点的唯一机制是顺序焦点导航。例如,键盘用户将无法单击具有负tabindex 的文本控件,因此该用户的用户代理有充分理由允许用户无论如何都切换到该控件。

如果值为零

用户代理必须允许将元素视为可聚焦区域,并应允许元素及其可聚焦区域(以元素作为其DOM 锚点可顺序聚焦

对于属于同一焦点导航范围tabindex 值 为零的元素和可聚焦区域,它们在tabindex 顺序焦点导航范围内的相对排序应按影子包含树的顺序进行。

如果值大于零

用户代理必须允许将元素视为可聚焦区域,并应允许元素及其可聚焦区域(以元素作为其DOM 锚点可顺序聚焦,并应将元素(在下文中引用为candidate)和上述可聚焦区域放置在元素所属的tabindex 顺序焦点导航范围中,以便相对于属于同一焦点导航范围的其他元素和可聚焦区域,它们是

HTMLElement/tabIndex

在所有当前引擎中支持。

Firefox1+Safari3.1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)18Internet Explorer🔰 5.5+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

tabIndex IDL 属性必须反映 tabindex 内容属性的值。如果元素是aareabuttonframeiframeinputobjectselecttextareaSVG a 元素,或是一个summary 元素是其父级 details 的摘要,则默认值 为 0。否则,默认值 为 −1。

基于元素类型不同的默认值是历史遗留问题。

6.6.4 处理模型

要为不是可聚焦区域的元素或可导航焦点目标获取可聚焦区域,并给定一个可选的字符串焦点触发器(默认为“other”),请运行以下列表中第一个匹配的步骤集

如果焦点目标 是一个area 元素,具有一个或多个可聚焦区域 的形状

返回与第一个使用该area元素所属图像地图的img元素对应的形状,该元素在树序中。

如果焦点目标是具有一个或多个可滚动区域的元素,并且这些区域是可聚焦区域

根据扁平树的先序深度优先遍历,返回元素的第一个可滚动区域。 [CSSSCOPING]

如果焦点目标是其Document文档元素

返回Document视窗.

如果焦点目标可导航的

返回可导航的活动文档.

如果焦点目标是具有非空内容可导航可导航容器

返回可导航容器内容可导航活动文档.

如果焦点目标影子宿主,其影子根委托焦点为真
  1. focusedElement当前顶级可遍历区域的焦点区域DOM 锚点.

  2. 如果焦点目标focusedElement包含影子的包含祖先,则返回focusedElement.

  3. 返回给定焦点触发器焦点目标焦点委托.

对于顺序可聚焦性,在构建顺序焦点导航顺序时,处理影子宿主委托焦点。也就是说,聚焦步骤永远不会在顺序焦点导航中调用此类影子宿主上。

否则

返回 null。

给定可选字符串focusTrigger(默认值为“other”)的focusTarget焦点委托由以下步骤给出

  1. 如果focusTarget影子宿主,并且其影子根委托焦点为假,则返回 null。

  2. whereToLookfocusTarget.

  3. 如果whereToLook影子宿主,则将whereToLook设置为whereToLook影子根.

  4. autofocusDelegate为给定focusTriggerwhereToLook自动焦点委托.

  5. 如果autofocusDelegate不为 null,则返回autofocusDelegate.

  6. 对于whereToLook后代中的每个descendant,在树序

    1. focusableArea为 null。

    2. 如果focusTargetdialog元素,并且descendant顺序可聚焦的,则将focusableArea设置为descendant.

    3. 否则,如果focusTarget不是dialog,并且descendant可聚焦区域,则将focusableArea设置为descendant.

    4. 否则,将focusableArea设置为获取给定focusTriggerdescendant的可聚焦区域的结果。

      此步骤可能最终导致递归,即获取可聚焦区域步骤可能返回descendant焦点委托.

    5. 如果focusableArea不为 null,则返回focusableArea.

    重要的是,我们在查看包含影子的后代,而仅查看后代影子宿主由上面提到的递归情况处理。

  7. 返回 null。

上面的算法本质上返回第一个合适的可聚焦区域,其DOM 锚点焦点目标之间的路径在任何影子树边界处委托焦点。

给定焦点触发器焦点目标自动焦点委托由以下步骤给出

  1. 对于焦点目标的每个后代descendant,在树序

    1. 如果descendant没有autofocus内容属性,则继续.

    2. 可聚焦区域descendant,如果descendant可聚焦区域;否则,设可聚焦区域获取给定焦点触发器descendant的可聚焦区域的结果。

    3. 如果可聚焦区域为 null,则继续.

    4. 如果可聚焦区域不是点击可聚焦的,并且焦点触发器为“click”,则继续.

    5. 返回可聚焦区域.

  2. 返回 null。

对于对象新的焦点目标聚焦步骤,该对象是可聚焦区域,或不是可聚焦区域的元素,或可导航的,如下所示。它们可以选择性地使用回退目标和字符串焦点触发器运行。

  1. 如果新的焦点目标不是可聚焦区域,则将新的焦点目标设置为获取给定焦点触发器新的焦点目标的可聚焦区域的结果(如果已传递)。

  2. 如果新的焦点目标为 null,则

    1. 如果没有指定回退目标,则返回。

    2. 否则,将新的焦点目标设置为回退目标.

  3. 如果新的焦点目标是具有非空内容可导航可导航容器,则将新的焦点目标设置为内容可导航活动文档.

  4. 如果新的焦点目标可聚焦区域,并且其DOM 锚点惰性的,则返回。

  5. 如果新的焦点目标当前顶级可遍历区域的焦点区域,则返回。

  6. 旧链新的焦点目标所在的顶级可遍历区域的当前焦点链.

  7. 新链新的焦点目标焦点链.

  8. 分别使用旧链新链新的焦点目标运行焦点更新步骤.

用户代理必须立即可聚焦区域可导航的候选运行聚焦步骤,无论何时用户尝试将焦点移动到候选

对于对象旧焦点目标取消焦点步骤,该对象是可聚焦区域或不是可聚焦区域的元素,如下所示

  1. 如果旧焦点目标影子宿主,其影子根委托焦点为真,并且旧焦点目标影子根当前顶级可遍历区域的焦点区域DOM 锚点包含影子的包含祖先,则将旧焦点目标设置为该当前顶级可遍历区域的焦点区域.

  2. 如果旧焦点目标惰性的,则返回。

  3. 如果 旧焦点目标 是一个 area 元素,并且它的一个形状是 当前聚焦的顶级可遍历区域,或者,如果 旧焦点目标 是一个具有一个或多个可滚动区域的元素,并且其中一个区域是 当前聚焦的顶级可遍历区域,那么让 旧焦点目标 成为那个 当前聚焦的顶级可遍历区域

  4. 旧链 成为 旧焦点目标 所在的 顶级可遍历的当前焦点链

  5. 如果 旧焦点目标 不是 旧链 中的条目之一,则返回。

  6. 如果 旧焦点目标 不是 可聚焦区域,则返回。

  7. 顶层文档 成为 旧链 的最后一个条目。

  8. 如果 顶层文档节点可遍历 具有 系统焦点,则运行 顶层文档视窗聚焦步骤

    否则,应用任何相关的平台特定约定从 顶层文档节点可遍历 中移除 系统焦点,并运行给定 旧链、一个空列表和空的 焦点更新步骤

失焦步骤 并不总是导致焦点改变,即使应用于 当前聚焦的顶级可遍历区域。例如,如果 当前聚焦的顶级可遍历区域 是一个 视窗,那么它通常会保留其焦点,直到另一个 可聚焦区域 使用 聚焦步骤 显式聚焦。


焦点更新步骤,分别给定一个 旧链、一个 新链 和一个 新焦点目标,如下所示

  1. 如果 旧链 中的最后一个条目和 新链 中的最后一个条目相同,则从 旧链 中弹出最后一个条目,从 新链 中弹出最后一个条目,并重做此步骤。

  2. 对于 旧链 中的每个条目 条目,按顺序运行以下子步骤

    1. 如果 条目 是一个 input 元素,并且 change 事件 应用 于该元素,并且该元素没有定义 激活行为,并且用户在控件聚焦时更改了该元素的 或其 所选文件 列表而没有提交该更改(使得它与控件首次聚焦时的状态不同),则

      1. 条目用户有效性 设置为 true。

      2. 触发一个名为 change 的事件,该事件在该元素上,bubbles 属性初始化为 true。

    2. 如果 条目 是一个元素,则让 失焦事件目标 成为 条目

      如果 条目 是一个 Document 对象,则让 失焦事件目标 成为该 Document 对象的 相关全局对象

      否则,让 失焦事件目标 为 null。

    3. 如果 条目旧链 中的最后一个条目,并且 条目 是一个 Element,并且 新链 中的最后一个条目也是一个 Element,则让 相关失焦目标 成为 新链 中的最后一个条目。否则,让 相关失焦目标 为 null。

    4. 如果 失焦事件目标 不为 null,则 触发一个名为 blur 的焦点事件,该事件在 失焦事件目标 上,相关失焦目标 作为相关目标。

      在某些情况下,例如,如果 条目 是一个 area 元素的形状、可滚动区域或 视窗,则不会触发任何事件。

  3. 应用任何相关的平台特定约定来聚焦 新焦点目标。(例如,某些平台在文本控件聚焦时会选择该控件的内容。)

  4. 对于 新链 中的每个条目 条目,以相反的顺序运行以下子步骤

    1. 如果 条目 是一个 可聚焦区域,并且 文档的聚焦区域 不是 条目

      1. 文档相关全局对象导航 API在进行中的导航期间焦点发生变化 设置为 true。

      2. 条目 指定为 文档的聚焦区域

    2. 如果 条目 是一个元素,则让 聚焦事件目标 成为 条目

      如果 条目 是一个 Document 对象,则让 聚焦事件目标 成为该 Document 对象的 相关全局对象

      否则,让 聚焦事件目标 为 null。

    3. 如果 条目新链 中的最后一个条目,并且 条目 是一个 Element,并且 旧链 中的最后一个条目也是一个 Element,则让 相关聚焦目标 成为 旧链 中的最后一个条目。否则,让 相关聚焦目标 为 null。

    4. 如果 聚焦事件目标 不为 null,则 触发一个名为 focus 的焦点事件,该事件在 聚焦事件目标 上,相关聚焦目标 作为相关目标。

      在某些情况下,例如,如果 条目 是一个 area 元素的形状、可滚动区域或 视窗,则不会触发任何事件。

触发一个名为 e 的焦点事件,该事件在元素 t 上,并具有给定的相关目标 r触发一个名为 e 的事件,该事件在 t 上,使用 FocusEvent,其中 relatedTarget 属性初始化为 rview 属性初始化为 t节点文档相关全局对象,并且 组合标志 被设置。


当一个键盘事件将在 顶级可遍历 中路由时,用户代理必须运行以下步骤

  1. 目标区域 成为 当前聚焦的顶级可遍历区域

  2. 断言目标区域 不为 null,因为键盘事件仅路由到具有 系统焦点顶级可遍历。因此,目标区域 是一个 可聚焦区域

  3. 目标节点 成为 目标区域DOM 锚点

  4. 如果 目标节点 是一个具有 主体元素Document,则让 目标节点 成为该 Document主体元素

    否则,如果 目标节点 是一个具有非空 文档元素Document 对象,则让 目标节点 成为该 文档元素

  5. 如果 目标节点 不是 惰性 的,则

    1. canHandle 成为 调度 目标节点 上的键盘事件的结果。

    2. 如果 canHandle 为 true,则让 目标区域 处理键盘事件。这可能包括 目标节点 上触发一个 click 事件


具有焦点步骤,给定一个 Document 对象 target,如下所示

  1. 如果 target节点可遍历顶级可遍历 没有 系统焦点,则返回 false。

  2. 候选 成为 target节点可遍历顶级可遍历活动文档

  3. 当为真时

    1. 如果 候选target,则返回 true。

    2. 如果 候选聚焦区域 是一个具有非空 内容可遍历可导航容器,则将 候选 设置为该 可导航容器内容可遍历活动文档

    3. 否则,返回 false。

6.6.5 顺序焦点导航

每个 文档 都有一个 顺序焦点导航顺序,它按顺序排列 文档 中的某些或所有 可聚焦区域。其内容和顺序由 文档扁平化 tabindex 排序的焦点导航范围 决定。

根据定义 扁平化 tabindex 排序的焦点导航范围 的规则,顺序不一定与 文档树形顺序 相关。

如果 可聚焦区域 被省略在所属 文档顺序焦点导航顺序 中,那么无法通过 顺序焦点导航 访问它。

还可能存在一个 顺序焦点导航起始点。它最初未设置。当用户指示应移动起始点时,用户代理可能会设置它。

例如,如果用户点击文档内容,用户代理可以将其设置为用户点击的位置。

导航到片段 时,用户代理必须将 顺序焦点导航起始点 设置为 目标元素

当用户请求将焦点从 当前聚焦的顶级可遍历区域 移动到下一个或上一个 可聚焦区域(例如,作为按 tab 键的默认操作),或者当用户请求将焦点顺序移动到一个 顶级可遍历区域 (例如,从浏览器的地址栏)时,用户代理必须使用以下算法

  1. 如果用户请求从那里顺序移动焦点,则将 起始点 设置为 当前聚焦的顶级可遍历区域;否则,如果用户请求从 顶级可遍历区域 之外移动焦点,则将其设置为 顶级可遍历区域 本身。

  2. 如果定义了 顺序焦点导航起始点 并且它位于 起始点 内,则将 起始点 设置为 顺序焦点导航起始点

  3. 如果用户请求 下一个 控件,则将 方向 设置为 向前;如果用户请求上一个控件,则将其设置为 向后

    通常,按 tab 请求下一个控件,按 shift + tab 请求上一个控件。

  4. 循环:如果 起始点 是一个 可导航区域 或者 起始点 在其 文档顺序焦点导航顺序 中,则将 选择机制 设置为 顺序

    否则,起始点 不在其 文档顺序焦点导航顺序 中;将 选择机制 设置为 DOM

  5. 候选 设置为使用 起始点方向选择机制 作为参数运行 顺序导航搜索算法 的结果。

  6. 如果 候选 不为 null,则对 候选 运行 聚焦步骤 并返回。

  7. 否则,取消设置 顺序焦点导航起始点

  8. 如果 起始点 是一个 顶级可遍历区域,或者是一个 可聚焦区域顶级可遍历区域 内,用户代理应将焦点适当转移到其自身的控件(如果有的话),并尊重 方向,然后返回。

    例如,如果 方向向后,则浏览器渲染区域之前的最后一个 可顺序聚焦的 控件将是需要聚焦的控件。

    如果用户代理没有 可顺序聚焦的 控件(例如,一个亭台模式的浏览器),则用户代理可以将 起始点 设置为 顶级可遍历区域 本身,重新开始这些步骤。

  9. 否则,起始点 是一个 可聚焦区域 在一个 子可导航区域 内。将 起始点 设置为该 子可导航区域父级 并返回到标记为 循环 的步骤。

顺序导航搜索算法 包含以下步骤。该算法接受三个参数:起始点方向选择机制

  1. 从下表中选择合适的单元格,并按照该单元格中的说明进行操作。

    合适的单元格是表头描述 方向 的列和表头描述 起始点选择机制 的第一行的交叉单元格。

    方向向前 方向向后
    起始点 是一个 可导航区域候选 设置为 起始点活动文档 中的第一个 合适的可顺序聚焦区域(如果有),否则为 null候选 设置为 起始点活动文档 中的最后一个 合适的可顺序聚焦区域(如果有),否则为 null
    选择机制DOM候选 设置为 主文档 中紧随 起始点 的第一个 合适的可顺序聚焦区域(如果有),否则为 null候选 设置为 主文档 中位于 起始点 之前的最后一个 合适的可顺序聚焦区域(如果有),否则为 null
    选择机制顺序候选 设置为 主顺序焦点导航顺序 中紧随 起始点 的第一个 合适的可顺序聚焦区域(如果有),否则为 null候选 设置为 主顺序焦点导航顺序 中位于 起始点 之前的最后一个 合适的可顺序聚焦区域(如果有),否则为 null

    一个 合适的可顺序聚焦区域 是一个 可聚焦区域,其 DOM 锚点 不为 惰性可顺序聚焦的

    主文档起始点 所属的 文档

    主顺序焦点导航顺序起始点 所属的 顺序焦点导航顺序

    主顺序焦点导航顺序主文档顺序焦点导航顺序,但仅在 起始点 在该 顺序焦点导航顺序 中时使用(如果不是,选择机制 将为 DOM)。

  2. 如果 候选 是一个具有非空 内容可导航区域可导航容器,则将 新候选 设置为使用 候选内容可导航区域 作为第一个参数、方向 作为第二个参数和 顺序 作为第三个参数运行 顺序导航搜索算法 的结果。

    如果 新候选 为 null,则将 起始点 设置为 候选,并返回到算法的开头。否则,将 候选 设置为 新候选

  3. Return candidate.

6.6.6 焦点管理 API

dictionary FocusOptions {
  boolean preventScroll = false;
  boolean focusVisible;
};
documentOrShadowRoot.activeElement

文档/activeElement

在所有当前引擎中支持。

Firefox3+Safari4+Chrome2+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer6+
Firefox Android?Safari iOS?Chrome Android?WebView Android37+Samsung Internet?Opera Android12.1+

ShadowRoot/activeElement

在所有当前引擎中支持。

Firefox63+Safari10+Chrome53+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

返回文档中接受按键事件的深度元素。简而言之,这就是文档中的聚焦元素。

在本 API 中,当一个子可导航元素获得焦点时,它的容器在其父级活动文档中获得焦点。例如,如果用户将焦点移动到iframe中的文本控件,那么iframeiframe节点文档activeElement API 返回的元素。

类似地,当获得焦点的元素位于与documentOrShadowRoot不同的节点树中时,如果documentOrShadowRoot是获得焦点元素的包含阴影的包含祖先,则返回位于与documentOrShadowRoot相同的节点树中的宿主;否则返回 null。

document.hasFocus()

文档/hasFocus

在所有当前引擎中支持。

Firefox3+Safari4+Chrome2+
Opera?Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS?Chrome Android?WebView Android37+Samsung Internet?Opera Android?

如果键盘事件正在通过或路由到文档,则返回 true;否则返回 false。大体上来说,这对应于文档(或嵌套在这个文档中的文档)获得焦点。

window.focus()

窗口/focus

在所有当前引擎中支持。

Firefox1+Safari1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android18+WebView Android?Samsung Internet?Opera Android12.1+

将焦点移动到窗口的可导航元素(如果有)。

element.focus([ { preventScroll: true } ])

HTMLElement/focus

在所有当前引擎中支持。

Firefox1.5+Safari3+Chrome1+
Opera8+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS1+Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

将焦点移动到该元素。

如果该元素是可导航容器,则将焦点移动到它的内容可导航元素

默认情况下,此方法还会将元素滚动到视图中。提供preventScroll 选项并将其设置为 true 会阻止此行为。

element.blur()

HTMLElement/blur

在所有当前引擎中支持。

Firefox1.5+Safari3+Chrome1+
Opera8+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS1+Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

将焦点移动到视窗。不建议使用此方法;如果要使视窗获得焦点,请在Document文档元素上调用focus() 方法。

如果您发现焦点环不好看,请不要使用此方法来隐藏焦点环。相反,请使用:focus-visible 伪类覆盖'outline' 属性,并提供其他方法来显示哪个元素获得了焦点。请注意,如果未提供替代的聚焦样式,则对于主要使用键盘导航页面或视力障碍者使用焦点轮廓来帮助他们导航页面的人来说,页面将难以使用。

例如,要隐藏来自textarea 元素的轮廓,并使用黄色背景来指示焦点,可以使用

textarea:focus-visible { outline: none; background: yellow; color: black; }

activeElement 属性的 getter 必须运行以下步骤

  1. candidate为这个DocumentOrShadowRoot节点文档焦点区域DOM 锚点

  2. candidate设置为重定向 candidate 到这个DocumentOrShadowRoot 的结果。

  3. 如果candidate根节点不是这个DocumentOrShadowRoot,则返回 null。

  4. 如果candidate不是Document 对象,则返回candidate

  5. 如果candidatebody 元素,则返回该body 元素

  6. 如果candidate文档元素不为 null,则返回该文档元素

  7. 返回 null。

Document 对象上调用hasFocus() 方法时,必须返回使用Document 对象作为参数运行有焦点步骤的结果。

调用focus() 方法时,必须运行以下步骤

  1. current为这个Window 对象的可导航元素

  2. 如果current为 null,则返回。

  3. 使用current运行聚焦步骤

  4. 如果current顶级可遍历元素,则鼓励用户代理触发某种通知以向用户表明页面正在尝试获取焦点。

窗口/blur

在所有当前引擎中支持。

Firefox1+Safari1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

blur() 方法的步骤是不做任何事。

从历史上看,focus()blur() 方法实际上会影响包含可导航元素的系统级小部件(例如,选项卡或窗口)的系统级焦点,但恶意网站广泛滥用此行为,对用户造成不利影响。

在元素上调用focus(options) 方法时,必须运行以下步骤

  1. 如果该元素被标记为锁定焦点,则返回。

  2. 将该元素标记为锁定焦点

  3. 为该元素运行聚焦步骤

  4. 如果optionsfocusVisible 字典成员的值为 true,或者不存在但以实现定义的方式用户代理确定最好这样做,则指示焦点

  5. 如果optionspreventScroll 字典成员的值为 false,则将元素滚动到视图中,使用 "auto"、"center" 和 "center"。

  6. 将该元素的锁定焦点 状态取消。

调用blur() 方法时,应为调用该方法的元素运行取消聚焦步骤。出于可用性原因,用户代理可以选择性地或统一地忽略对该方法的调用。

例如,如果blur() 方法不明智地用于出于美观原因删除焦点环,则键盘用户将无法使用页面。因此,忽略对该方法的调用将允许键盘用户与页面进行交互。

6.6.7 autofocus 属性

autofocus 内容属性允许作者指示在页面加载后立即使某个元素获得焦点,从而允许用户只需开始输入,而无需手动使主元素获得焦点。

当在dialog 元素内部或popover 属性已设置的HTML 元素内部指定autofocus 属性时,在对话框或弹出窗口显示时,它将获得焦点。

autofocus 属性是一个布尔属性

要找到给定Element element最近的祖先自动聚焦作用域根元素

  1. 如果element 是一个dialog 元素,则返回element

  2. 如果elementpopover 属性不在无弹出窗口状态,则返回element

  3. ancestorelement

  4. ancestor父元素

    1. ancestor 设置为ancestor父元素

    2. 如果 ancestor 是一个 dialog 元素,则返回 ancestor

    3. 如果 ancestorpopover 属性不在 无弹出状态 中,则返回 ancestor

  5. 返回 ancestor

不能有两个元素具有相同的 最近的祖先自动聚焦作用域根元素,并且都指定了 autofocus 属性。

每个 Document 都有一个 自动聚焦候选者 列表,最初为空。

每个 Document 都有一个 自动聚焦处理标志 布尔值,最初为 false。

当指定了 autofocus 属性的元素 插入到文档中 时,运行以下步骤

  1. 如果用户已经表明(例如,通过开始在表单控件中输入)他们不希望焦点发生改变,则可以选择性地返回。

  2. target 为元素的 节点文档

  3. 如果 target 不是 完全活动 的,则返回。

  4. 如果 target活动沙箱标志集 包含 沙箱自动功能浏览上下文标志,则返回。

  5. 对于 target祖先可导航元素 的每个 ancestorNavigable:如果 ancestorNavigable活动文档来源target来源同源,则返回。

  6. topDocumenttarget节点可导航元素顶级可遍历元素活动文档

  7. 如果 topDocument自动聚焦处理标志 为 false,则 移除 该元素从 topDocument自动聚焦候选者 中,并 追加 该元素到 topDocument自动聚焦候选者 中。

我们不会在将元素存储在 自动聚焦候选者 列表中之前检查它是否是 可聚焦区域,因为即使它在插入时不是可聚焦区域,它也可能在 刷新自动聚焦候选者 看到它时变成可聚焦区域。

为了 刷新自动聚焦候选者 针对文档 topDocument,运行以下步骤

  1. 如果 topDocument自动聚焦处理标志 为 true,则返回。

  2. candidatestopDocument自动聚焦候选者

  3. 如果 candidates 为空,则返回。

  4. 如果 topDocument活动区域 不是 topDocument 本身,或者 topDocument 具有非空 目标元素,则

    1. 清空 candidates

    2. topDocument自动聚焦处理标志 设置为 true。

    3. 返回。

  5. candidates 不是

    1. elementcandidates[0]。

    2. docelement节点文档

    3. 如果 doc 不是 完全活动 的,则 移除 elementcandidates 中,并 继续

    4. 如果 doc节点可导航元素顶级可遍历元素topDocument节点可导航元素 不相同,则 移除 elementcandidates 中,并 继续

    5. 如果 doc阻止脚本样式表集 不是 的,则返回。

      在这种情况下,element 是当前最佳候选者,但 doc 尚未准备好进行自动聚焦。我们将在下次调用 刷新自动聚焦候选者 时再次尝试。

    6. 移除 elementcandidates 中。

    7. inclusiveAncestorDocuments 为一个 列表,其中包含 doc包含的祖先可导航元素活动文档

    8. 如果 inclusiveAncestorDocuments 中的任何 Document 具有非空 目标元素,则 继续

    9. targetelement

    10. 如果 target 不是 可聚焦区域,则将 target 设置为 获取可聚焦区域 针对 target 的结果。

      自动聚焦候选者 可以 包含 不是 可聚焦区域 的元素。除了在 获取可聚焦区域 算法中处理的特殊情况之外,这可能是因为具有 autofocus 属性的非 可聚焦区域 元素 插入到文档中 并且从未变得可聚焦,或者因为该元素是可聚焦的,但它的状态在存储在 自动聚焦候选者 中时发生了改变。

    11. 如果 target 不为空,则

      1. 清空 candidates

      2. topDocument自动聚焦处理标志 设置为 true。

      3. 针对 target 运行 聚焦步骤

这处理文档加载期间的自动聚焦。 show()showModal() 方法 dialog 元素也会处理 autofocus 属性。

聚焦该元素并不意味着用户代理必须聚焦浏览器窗口,如果它已经失去焦点。

Global_attributes/autofocus

仅在一个引擎中支持。

Firefox🔰 1+Safari🔰 4+Chrome79+
Opera66+Edge79+
Edge (Legacy)NoInternet Explorer🔰 10+
Firefox Android?Safari iOS?Chrome Android?WebView Android79+Samsung Internet?Opera Android57+

autofocus IDL 属性必须 反映 同名内容属性。

在以下代码片段中,文本控件将在文档加载时获得焦点。

<input maxlength="256" name="q" value="" autofocus>
<input type="submit" value="Search">

autofocus 属性适用于所有元素,而不仅仅是表单控件。这允许以下示例

<div contenteditable autofocus>Edit <strong>me!</strong><div>

6.7 分配键盘快捷键

6.7.1 简介

本节为非规范性内容。

每个可以激活或聚焦的元素都可以分配一个唯一的键组合来激活它,使用 accesskey 属性。

确切的快捷键由用户代理根据用户键盘的信息、平台上已存在的键盘快捷键以及在页面上使用 accesskey 属性中提供的信息作为指南指定的其他快捷键来确定。

为了确保在各种输入设备上都提供相关的键盘快捷键,作者可以在 accesskey 属性中提供多个备选方案。

每个备选方案都包含一个单个字符,例如字母或数字。

用户代理可以为用户提供键盘快捷键列表,但作者也鼓励这样做。 accessKeyLabel IDL 属性返回一个字符串,表示用户代理分配的实际键组合。

在这个示例中,作者提供了一个按钮,可以使用快捷键调用。为了支持完整的键盘,作者提供了“C”作为可能的键。为了支持仅配备数字键盘的设备,作者提供了“1”作为另一个可能的键。

<input type=button value=Collect onclick="collect()"
       accesskey="C 1" id=c>

为了告诉用户快捷键是什么,作者在这里选择了显式地将键组合添加到按钮的标签中

function addShortcutKeyLabel(button) {
  if (button.accessKeyLabel != '')
    button.value += ' (' + button.accessKeyLabel + ')';
}
addShortcutKeyLabel(document.getElementById('c'));

不同平台上的浏览器即使对于相同的键组合也会显示不同的标签,这取决于该平台上普遍的约定。例如,如果键组合是 Control 键、Shift 键和字母 C,Windows 浏览器可能会显示“Ctrl+Shift+C”,而 Mac 浏览器可能会显示“^⇧C”,而 Emacs 浏览器可能只显示“C-C”。同样,如果键组合是 Alt 键和 Escape 键,Windows 可能会使用“Alt+Esc”,Mac 可能会使用“⌥⎋”,而 Emacs 浏览器可能会使用“M-ESC”或“ESC ESC”。

因此,一般来说,尝试解析从 accessKeyLabel IDL 属性返回的值是不明智的。

6.7.2 accesskey 属性

Global_attributes/accesskey

在所有当前引擎中支持。

Firefox1+Safari4+Chrome1+
Opera?Edge79+
Edge (Legacy)12+Internet ExplorerYes
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

所有 HTML 元素 都可以设置 accesskey 内容属性。用户代理使用 accesskey 属性的值作为创建键盘快捷键的指南,该快捷键可以激活或聚焦元素。

如果指定,该值必须是 按顺序排列的唯一空格分隔标记集,其中没有一个标记与另一个标记 相同,并且每个标记都必须恰好是一个代码点长度。

在以下示例中,给出了各种带有访问键的链接,以便熟悉该网站的键盘用户可以更快地导航到相关页面

<nav>
 <p>
  <a title="Consortium Activities" accesskey="A" href="/Consortium/activities">Activities</a> |
  <a title="Technical Reports and Recommendations" accesskey="T" href="/TR/">Technical Reports</a> |
  <a title="Alphabetical Site Index" accesskey="S" href="/Consortium/siteindex">Site Index</a> |
  <a title="About This Site" accesskey="B" href="/Consortium/">About Consortium</a> |
  <a title="Contact Consortium" accesskey="C" href="/Consortium/contact">Contact</a>
 </p>
</nav>

在以下示例中,搜索字段被赋予了两个可能的访问键,“s”和“0”(按此顺序)。在具有完整键盘的设备上的用户代理可能会选择 Ctrl + Alt + S 作为快捷键,而仅具有数字键盘的小型设备上的用户代理可能会选择简单的无修饰键 0

<form action="/search">
 <label>Search: <input type="search" name="q" accesskey="s 0"></label>
 <input type="submit">
</form>

在以下示例中,一个按钮具有可能的访问键描述。然后,一个脚本尝试更新按钮的标签,以宣传用户代理选择的键组合。

<input type=submit accesskey="N @ 1" value="Compose">
...
<script>
 function labelButton(button) {
   if (button.accessKeyLabel)
     button.value += ' (' + button.accessKeyLabel + ')';
 }
 var inputs = document.getElementsByTagName('input');
 for (var i = 0; i < inputs.length; i += 1) {
   if (inputs[i].type == "submit")
     labelButton(inputs[i]);
 }
</script>

在一个用户代理中,按钮的标签可能会变成“Compose (⌘N)”。在另一个用户代理中,它可能会变成“Compose (Alt+⇧+1)”。如果用户代理没有分配键,它将只是“Compose”。确切的字符串取决于 分配的访问键 以及用户代理如何表示该键组合。

6.7.3 处理模型

元素的 分配的访问键 是从元素的 accesskey 内容属性派生的键组合。最初,元素 必须没有分配的访问键

每当元素的 accesskey 属性被设置、更改或删除时,用户代理必须通过运行以下步骤来更新元素的 分配的访问键

  1. 如果元素没有 accesskey 属性,则跳过下面的回退步骤。

  2. 否则,按 ASCII 空格拆分属性的值,并将 keys 设为生成的标记。

  3. 对于 keys 中的每个值,依次按标记在属性值中出现的顺序,运行以下子步骤

    1. 如果该值不是一个恰好一个代码点长度的字符串,则跳过对该值的这些步骤的剩余部分。

    2. 如果该值不对应于系统键盘上的键,则跳过对该值的这些步骤的剩余部分。

    3. (这是一个跟踪向量。) 如果用户代理可以找到零个或多个修饰键的组合,这些修饰键与对应于属性中给定值的键结合在一起可以用作访问键,则用户代理可以将该键组合分配为元素的 分配的访问键 并返回。

  4. 回退:用户代理可以选择性地将它选择的键组合分配为元素的 分配的访问键,然后返回。

  5. 如果达到此步骤,则元素没有 分配的访问键

一旦用户代理为元素选择了并分配了访问键,用户代理不应该更改元素的 分配的访问键,除非 accesskey 内容属性被更改或元素被移动到另一个 Document

当用户按下与元素的 分配的访问键 对应的键组合时,如果元素 定义了一个命令,则该命令的 隐藏状态 面是 false(可见),该命令的 禁用状态 面也是 false(启用),该元素 在具有非空 浏览上下文 的文档中,并且该元素或其任何祖先都没有指定的 hidden 属性,则用户代理必须触发该命令的 操作

用户代理 可能会以其他方式公开 具有 accesskey 属性的元素,例如在响应特定键组合而显示的菜单中。


HTMLElement/accessKey

在所有当前引擎中支持。

Firefox5+Safari6+Chrome17+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

accessKey IDL 属性必须 反映 accesskey 内容属性。

HTMLElement/accessKeyLabel

Firefox8+Safari14+ChromeNo
Opera?EdgeNo
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

accessKeyLabel IDL 属性必须返回一个字符串,该字符串表示元素的 分配的访问键(如果有)。如果元素没有分配的访问键,则该 IDL 属性必须返回空字符串。

6.8 编辑

6.8.1 使文档区域可编辑:contenteditable 内容属性

HTMLElement/contentEditable

在所有当前引擎中支持。

Firefox3+Safari3+Chrome1+
Opera9+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS1+Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+
interface mixin ElementContentEditable {
  [CEReactions] attribute DOMString contentEditable;
  [CEReactions] attribute DOMString enterKeyHint;
  readonly attribute boolean isContentEditable;
  [CEReactions] attribute DOMString inputMode;
};

Global_attributes/contenteditable

在所有当前引擎中支持。

Firefox3+Safari4+Chrome1+
Opera9+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

contenteditable 内容属性是具有以下关键字和状态的 枚举属性

关键字状态简要描述
true true 该元素是可编辑的。
(空字符串)
false false 该元素不可编辑。
plaintext-only plaintext-only 只有元素的原始文本内容是可编辑的;富格式化被禁用。

该属性的 缺少值默认值无效值默认值 都是 inherit 状态。inherit 状态表示元素的可编辑性(或不可编辑性)取决于父元素的状态。

例如,考虑一个页面,该页面有一个 form 和一个 textarea 用于发布新文章,其中用户希望使用 HTML 来编写文章

<form method=POST>
 <fieldset>
  <legend>New article</legend>
  <textarea name=article>&lt;p>Hello world.&lt;/p></textarea>
 </fieldset>
 <p><button>Publish</button></p>
</form>

当启用脚本时,textarea 元素可以使用 contenteditable 属性替换为富文本控件。

<form method=POST>
 <fieldset>
  <legend>New article</legend>
  <textarea id=textarea name=article>&lt;p>Hello world.&lt;/p></textarea>
  <div id=div style="white-space: pre-wrap" hidden><p>Hello world.</p></div>
  <script>
   let textarea = document.getElementById("textarea");
   let div = document.getElementById("div");
   textarea.hidden = true;
   div.hidden = false;
   div.contentEditable = "true";
   div.oninput = (e) => {
     textarea.value = div.innerHTML;
   };
  </script>
 </fieldset>
 <p><button>Publish</button></p>
</form>

要启用的功能(例如,插入链接)可以使用 document.execCommand() API 实现,或者使用 Selection API 和其他 DOM API 实现。 [EXECCOMMAND] [SELECTION] [DOM]

contenteditable 属性也可以非常有效地使用

<!doctype html>
<html lang=en>
<title>Live CSS editing!</title>
<style style=white-space:pre contenteditable>
html { margin:.2em; font-size:2em; color:lime; background:purple }
head, title, style { display:block }
body { display:none }
</style>
element.contentEditable [ = value ]

根据 contenteditable 属性的状态,返回“true”、“plaintext-only”、“false”或“inherit”。

可以设置,以更改该状态。

如果新值不是这些字符串之一,则抛出 "SyntaxError" DOMException

element.isContentEditable

HTMLElement/isContentEditable

在所有当前引擎中支持。

Firefox4+Safari3+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+Internet Explorer5.5+
Firefox Android?Safari iOS1+Chrome Android?WebView Android?Samsung Internet?Opera Android12.1+

如果该元素是可编辑的,则返回 true;否则,返回 false。

获取时,contentEditable IDL 属性必须返回字符串 "true",如果 content 属性设置为 true 状态;返回字符串 "plaintext-only",如果 content 属性设置为 plaintext-only 状态;返回字符串 "false",如果 content 属性设置为 false 状态;返回字符串 "inherit",否则。设置时,如果新值与字符串 "inherit" 不区分大小写 匹配,则必须移除 content 属性;如果新值与字符串 "true" 不区分大小写 匹配,则必须将 content 属性设置为字符串 "true";如果新值与字符串 "plaintext-only" 不区分大小写 匹配,则必须将 content 属性设置为字符串 "plaintext-only";如果新值与字符串 "false" 不区分大小写 匹配,则必须将 content 属性设置为字符串 "false";否则,属性设置器必须抛出一个 "SyntaxError" DOMException

获取时,isContentEditable IDL 属性必须返回 true,如果元素是 编辑宿主可编辑的,否则返回 false。

6.8.2 使整个文档可编辑:designMode IDL 属性的 getter 和 setter

document.designMode [ = value ]

Document/designMode

在所有当前引擎中支持。

Firefox1+Safari1.2+Chrome1+
Opera9+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

如果文档可编辑,则返回 "on",否则返回 "off"。

可以设置,以更改文档的当前状态。这将使文档获得焦点,并重置该文档中的选择。

Document 对象具有一个关联的 design mode enabled,它是一个布尔值。它最初为 false。

designMode getter 步骤是:如果 thisdesign mode enabled 为 true,则返回 "on";否则返回 "off"。

designMode setter 步骤是:

  1. value 设置为给定的值,转换为 ASCII 小写

  2. 如果 value 为 "on" 且 thisdesign mode enabled 为 false,则:

    1. thisdesign mode enabled 设置为 true。

    2. this活动范围 的开始和结束边界点设置为 this 的开头。

    3. this文档元素(如果非空)运行 聚焦步骤

  3. 如果 value 为 "off",则将 thisdesign mode enabled 设置为 false。

6.8.3 页面内编辑器的最佳实践

鼓励作者在 编辑宿主 上以及在通过这些编辑机制最初创建的标记上,将 'white-space' 属性设置为 'pre-wrap' 值。默认的 HTML 空白处理不适合所见即所得编辑,如果将 'white-space' 保留在其默认值,则在某些特殊情况下,换行将无法正常工作。

例如,如果使用默认的 'normal' 值,则会遇到问题,例如用户输入 "yellow␣␣ball",单词之间有两个空格(这里用 "␣" 表示)。使用针对 'white-space' 的默认值 ('normal') 制定的编辑规则,生成的标记将包含 "yellow&nbsp; ball" 或 "yellow &nbsp;ball";也就是说,除了普通空格之外,两个单词之间还会有一个不间断空格。这是必需的,因为 'white-space' 的 'normal' 值要求将相邻的普通空格合并在一起。

在前一种情况下,"yellow空格" 可能会换行到下一行(这里使用 "空格" 表示不间断空格),即使 "yellow" 本身可能适合放在行尾;在后一种情况下,"空格ball"(如果换行到行首)将会有不间断空格带来的可见缩进。

但是,当 'white-space' 设置为 'pre-wrap' 时,编辑规则将改为简单地将两个普通空格放在单词之间,如果这两个单词在行尾被拆分,则空格将被从呈现中整齐地移除。

6.8.4 编辑 API

编辑宿主HTML 元素(其 contenteditable 属性处于 true 状态或 plaintext-only 状态),或者 HTML 元素(其 Documentdesign mode enabled 为 true)。

术语 活动范围编辑宿主 of可编辑的 的定义,编辑宿主可编辑的 元素的用户界面要求,execCommand()queryCommandEnabled()queryCommandIndeterm()queryCommandState()queryCommandSupported()queryCommandValue() 方法,文本选择以及 删除选择 算法在 execCommand 中定义。 [EXECCOMMAND]

6.8.5 拼写和语法检查

用户代理可以支持对可编辑文本的拼写和语法检查,无论是表单控件(例如 textarea 元素的值)还是 编辑宿主 中的元素(例如使用 contenteditable)。

对于每个元素,用户代理必须通过默认设置或用户表示的偏好,确定 默认行为。每个元素有三种可能的默认行为

true-by-default
如果元素的内容可编辑且未通过 spellcheck 属性明确禁用拼写检查,则将对该元素进行拼写和语法检查。
false-by-default
除非通过 spellcheck 属性明确启用拼写检查,否则将不会对该元素进行拼写和语法检查。
inherit-by-default
元素的默认行为与其父元素相同。没有父元素的元素不能将其作为默认行为。

Global_attributes/spellcheck

在所有当前引擎中支持。

FirefoxYesSafariYesChrome9+
OperaYesEdge79+
旧版 Edge12+Internet Explorer11
Firefox Android57+Safari iOS9.3+Chrome Android47+WebView Android?Samsung Internet?Opera Android37+

spellcheck 属性是一个 枚举属性,具有以下关键字和状态

关键字状态简要描述
true true 将检查拼写和语法。
(空字符串)
false false 将不会检查拼写和语法。

该属性的 缺失值默认值无效值默认值 均为 默认 状态。默认状态表示元素将根据默认行为,可能根据父元素的 spellcheck 状态,按照下面定义的方式进行操作。


element.spellcheck [ = value ]

如果元素要进行拼写和语法检查,则返回 true;否则,返回 false。

可以设置,以覆盖默认值并设置 spellcheck 内容属性。

spellcheck IDL 属性在获取时,如果元素的 spellcheck 内容属性处于 true 状态,或者元素的 spellcheck 内容属性处于 默认 状态且元素的 默认行为默认启用,或者元素的 spellcheck 内容属性处于 默认 状态且元素的 默认行为默认继承 且元素的父元素的 spellcheck IDL 属性会返回 true;否则,如果以上条件都不满足,则属性必须返回 false。

spellcheck IDL 属性不受覆盖 spellcheck 内容属性的用户偏好的影响,因此可能无法反映实际的拼写检查状态。

在设置时,如果新值为 true,则元素的 spellcheck 内容属性必须设置为 "true",否则必须设置为 "false"。


用户代理应该只将以下文本部分视为此功能的检查对象

对于作为 Text 节点一部分的文本,与文本关联的元素是单词、句子或其他文本的第一個字符的直接父元素。对于属性中的文本,它是属性的元素。对于 inputtextarea 元素的值,它是元素本身。

要确定适用元素(如上所定义)中的单词、句子或其他文本是否启用拼写和语法检查,UA 必须使用以下算法

  1. 如果用户已禁用此文本的检查,则检查被禁用。
  2. 否则,如果用户已强制此文本的检查始终启用,则检查被启用。
  3. 否则,如果与文本关联的元素具有 spellcheck 内容属性,则:如果该属性处于 true 状态,则检查被启用;否则,如果该属性处于 false 状态,则检查被禁用。
  4. 否则,如果存在具有 spellcheck 内容属性且不处于 默认 状态的祖先元素,则:如果最近的此类祖先的 spellcheck 内容属性处于 true 状态,则检查被启用;否则,检查被禁用。
  5. 否则,如果元素的 默认行为默认启用,则检查被启用。
  6. 否则,如果元素的 默认行为默认禁用,则检查被禁用。
  7. 否则,如果元素的父元素启用了其检查,则检查被启用。
  8. 否则,检查被禁用。

如果为单词/句子/文本启用了检查,用户代理应该在该文本中指示拼写和语法错误。用户代理在建议拼写和语法更正时应该考虑文档中给出的其他语义。用户代理可以使用元素的语言来确定使用哪些拼写和语法规则,或者可以使用用户的首选语言设置。UA 应该使用 input 元素属性(例如 pattern)以确保结果值有效,如果可能的话。

如果检查被禁用,用户代理不应该指示该文本的拼写或语法错误。

以下示例中,ID 为 "a" 的元素将用于确定是否检查 "Hello" 一词的拼写错误。在此示例中,它不会被检查。

<div contenteditable="true">
 <span spellcheck="false" id="a">Hell</span><em>o!</em>
</div>

以下示例中,ID 为 "b" 的元素将启用检查(input 元素上的属性值中的前导空格会导致属性被忽略,因此无论默认值如何,都会使用祖先的值)。

<p spellcheck="true">
 <label>Name: <input spellcheck=" false" id="b"></label>
</p>

本规范没有定义拼写和语法检查的用户界面。用户代理可以提供按需检查,可以在启用检查时执行连续检查,或者可以使用其他界面。

6.8.6 写作建议

当用户在可编辑区域(例如在表单控件(例如 textarea 元素)中或在 编辑主机 中的元素中)中键入时,用户代理会提供写作建议。

writingsuggestions 内容属性是一个 枚举属性,具有以下关键字和状态

关键字状态简要描述
true true 应该为此元素提供写作建议。
(空字符串)
false false 不应该为此元素提供写作建议。

属性的 缺失值默认值默认 状态。默认状态表示元素将根据默认行为进行操作,这可能是基于父元素自身的 writingsuggestions 状态,如下所述。

属性的 无效值默认值true 状态。

element.writingSuggestions [ = value ]

如果用户代理要在元素范围内提供写作建议,则返回 "true";否则,返回 "false"。

可以设置,以覆盖默认值并设置 writingsuggestions 内容属性。

给定 element计算写作建议值 通过运行以下步骤来确定

  1. 如果 elementwritingsuggestions 内容属性处于 false 状态,则返回 "false"。

  2. 如果 elementwritingsuggestions 内容属性处于 默认 状态,element 具有父元素,并且 element 的父元素的 计算写作建议值 为 "false",则返回 "false"。

  3. 返回 "true"。

writingSuggestions 获取器步骤如下

  1. 返回 this计算写作建议值

writingSuggestions IDL 属性不受覆盖 writingsuggestions 内容属性的用户偏好的影响,因此可能无法反映实际的写作建议状态。

writingSuggestions 设置器步骤如下

  1. thiswritingsuggestions 内容属性设置为给定值。


用户代理应该只在元素的范围内提供建议,如果给定 element 运行以下算法的结果返回 true

  1. 如果用户已禁用写作建议,则返回 false。

  2. 如果以下条件都不成立

    则返回 false。

  3. 如果 element 具有一个 包含祖先,其 writingsuggestions 内容属性不在 默认 状态,并且最近的此类祖先的 writingsuggestions 内容属性处于 false 状态,则返回 false。

  4. 否则,返回 true。

本规范没有定义书写建议的用户界面。用户代理可以提供按需建议、用户键入时的持续建议、内联建议、弹出窗口中的类似自动填充的建议,或者可以使用其他界面。

6.8.7 自动大写

一些输入文本的方法,例如移动设备上的虚拟键盘,以及语音输入,通常通过自动将句子首字母大写来帮助用户(在使用此约定的语言中撰写文本时)。实现自动大写的虚拟键盘可能会在要键入应自动大写的字母时自动切换为显示大写字母(但允许用户将其切换回小写)。其他类型的输入(例如语音输入)可能会以一种不提供用户先干预选择的方式执行自动大写。这 autocapitalize 属性允许作者控制此类行为。

autocapitalize 属性,在典型的实现方式中,不会影响在物理键盘上键入时的行为。(因此,以及用户在某些情况下可以覆盖自动大写行为或在初始输入后编辑文本的能力,该属性不能依赖于任何类型的输入验证。)

autocapitalize 属性可以在 编辑宿主 上使用以控制托管的可编辑区域的自动大写行为,在一个 inputtextarea 元素上以控制将文本输入到该元素的行为,或者在一个 form 元素上以控制与该 form 元素关联的所有 自动大写和自动更正继承元素 的默认行为。

autocapitalize 属性绝不会导致 input 元素的自动大写被启用,其 type 属性处于 URLEmailPassword 状态。(此行为包含在以下 已使用的自动大写提示 算法中。)

自动大写处理模型基于在五个 自动大写提示 中进行选择,定义如下

default

用户代理和输入方法应自行决定是否启用自动大写。

none

不应应用自动大写(所有字母应默认为小写)。

sentences

每个句子的首字母应默认为大写字母;所有其他字母应默认为小写。

words

每个单词的首字母应默认为大写字母;所有其他字母应默认为小写。

characters

所有字母应默认为大写。

Global_attributes/autocapitalize

在所有当前引擎中支持。

Firefox111+SafariNoChrome43+
Opera?Edge79+
Edge (Legacy)?Internet Explorer?
Firefox Android?Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android?

autocapitalize 属性是一个 枚举属性,其状态是可能的 自动大写提示。这 自动大写提示 由属性的状态指定,与其他考虑因素相结合形成 已使用的自动大写提示,它会通知用户代理的行为。此属性的关键字及其状态映射如下

关键字状态
off none
none
on sentences
sentences
words words
characters characters

属性的 缺失值默认值default 状态,其 无效值默认值sentences 状态。

element.autocapitalize [ = value ]

返回元素的当前自动大写状态,或者如果未设置则返回空字符串。注意,对于从 form 元素继承其状态的 inputtextarea 元素,这将返回 form 元素的自动大写状态,但对于可编辑区域中的元素,这将不会返回编辑宿主的自动大写状态(除非该元素实际上是 编辑宿主)。

可以设置,以设置 autocapitalize 内容属性(从而改变元素的自动大写行为)。

要计算元素 element自身自动大写提示,请运行以下步骤

  1. 如果 autocapitalize 内容属性在 element 上存在,并且其值为非空字符串,则返回属性的状态。

  2. 如果 element 是一个 自动大写和自动更正继承元素 并且具有一个非空 表单所有者,则返回 element自身自动大写提示表单所有者

  3. 返回 default

autocapitalize getter 步骤是

  1. statethis自身自动大写提示

  2. 如果 statedefault,则返回空字符串。

  3. 如果 statenone,则返回 "none"。

  4. 如果 statesentences,则返回 "sentences"。

  5. 返回与 state 相对应的关键字值。

autocapitalize setter 步骤是将 autocapitalize 内容属性设置为给定值。


支持文本输入方法的可自定义自动大写行为并希望允许 Web 开发人员控制此功能的用户代理应该在将文本输入元素时计算元素的 已使用的自动大写提示。这将是一个 自动大写提示,它描述了将文本输入到元素的推荐自动大写行为。

用户代理或输入方法可以选择在某些情况下忽略或覆盖 已使用的自动大写提示

元素 element已使用的自动大写提示 使用以下算法计算

  1. 如果 element 是一个 input 元素,其 type 属性处于 URLEmailPassword 状态,则返回 default

  2. 如果 element 是一个 input 元素或一个 textarea 元素,则返回 element自身自动大写提示

  3. 如果 element 是一个 编辑宿主 或一个 可编辑的 元素,则返回 element编辑宿主自身自动大写提示

  4. 断言:此步骤永远不会被执行,因为文本输入只发生在满足上述条件之一的元素中。

6.8.8 自动更正

一些输入文本的方法通过在键入时自动更正拼写错误的单词来帮助用户,此过程也称为自动更正。用户代理可以支持可编辑文本的自动更正,无论是在表单控件中(例如 textarea 元素的值),还是在 编辑宿主 中的元素中(例如,使用 contenteditable)。自动更正可能伴随着用户界面,指示文本即将被自动更正或已被自动更正,并且通常在拼写错误的单词后插入标点符号、空格或新段落时执行。这 autocorrect 属性允许作者控制此类行为。

在编辑宿主上,autocorrect 属性可以用于控制托管可编辑区域的自动更正行为;在 inputtextarea 元素上,可以用于控制在向该元素插入文本时的行为;在 form 元素上,可以用于控制与 form 元素关联的所有 继承自动大写和小写的元素 的默认行为。

对于 input 元素,其 type 属性为 URL电子邮件密码 状态,autocorrect 属性永远不会导致为其启用自动更正。(此行为包含在下面 使用的自动更正状态 算法中。)

autocorrect 属性是一个枚举属性,具有以下关键字和状态

关键字状态简要描述
on on 用户代理可以在用户输入时自动更正拼写错误。是否在输入时自动更正拼写错误,由用户代理决定,可能取决于元素以及用户的首选项。
(空字符串)
off off 用户代理不允许在用户输入时自动更正拼写错误。

属性的 无效值默认值缺失值默认值 都是 on 状态。

autocorrect 获取步骤:如果元素的 使用的自动更正状态on,则返回 true;如果元素的 使用的自动更正状态off,则返回 false。设置步骤:如果给定值为 true,则元素的 autocorrect 属性必须设置为 "on";否则必须设置为 "off"。

要计算元素 element使用的自动更正状态,请执行以下步骤

  1. 如果 element 是一个 input 元素,其 type 属性为 URL电子邮件密码 状态,则返回 off

  2. 如果 autocorrect 内容属性存在于 element 上,则返回属性的状态。

  3. 如果 element 是一个 继承自动大写和小写的元素,并且具有非空的 表单所有者,则返回 element表单所有者autocorrect 属性的状态。

  4. 返回 on

element . autocorrect

返回元素的自动更正行为。请注意,对于从 form 元素继承其状态的 继承自动大写和小写的元素,这将返回 form 元素的自动更正行为,但对于可编辑区域中的元素,这将不会返回 编辑宿主 的自动更正行为(除非该元素实际上是 编辑宿主)。

element . autocorrect = value

更新 autocorrect 内容属性(并因此更改元素的自动更正行为)。

在以下示例中,input 元素不允许自动更正,因为它没有 autocorrect 内容属性,因此从 form 元素继承,该元素的属性为 "off"。但是,textarea 元素将允许自动更正,因为它具有 autocorrect 内容属性,其值为 "on"。

<form autocorrect="off">
 <input type="search">
 <textarea autocorrect="on"></textarea>
</form>

6.8.9 输入方式:inputmode 属性

用户代理可以在表单控件(如 textarea 元素的值)或编辑宿主中的元素(例如使用 contenteditable)上支持 inputmode 属性。

Global_attributes/inputmode

在所有当前引擎中支持。

Firefox95+SafariChrome66+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android79+Safari iOS12.2+Chrome Android?WebView Android?Samsung Internet?Opera Android?

inputmode 内容属性是一个 枚举属性,它指定对用户输入内容最有效的输入机制类型。

关键字描述
none 用户代理不应显示虚拟键盘。此关键字适用于呈现自己的键盘控件的内容。
text 用户代理应显示一个能够以用户区域设置进行文本输入的虚拟键盘。
tel 用户代理应显示一个能够输入电话号码的虚拟键盘。这应包括用于数字 0 到 9、"#" 字符和 "*" 字符的键。在某些区域设置中,这还可以包括字母助记标签(例如,在美国,标记为 "2" 的键在历史上也标记为字母 A、B 和 C)。
url 用户代理应显示一个能够以用户区域设置进行文本输入的虚拟键盘,并包含用于帮助输入 URL 的键,例如用于 "/" 和 "." 字符的键,以及用于快速输入通常在域名中找到的字符串的键,例如 "www." 或 ".com"。
email 用户代理应显示一个能够以用户区域设置进行文本输入的虚拟键盘,并包含用于帮助输入电子邮件地址的键,例如用于 "@" 字符和 "." 字符的键。
numeric 用户代理应显示一个能够进行数字输入的虚拟键盘。此关键字适用于 PIN 输入。
decimal 用户代理应显示一个能够进行分数数字输入的虚拟键盘。应显示数字键和区域设置的格式分隔符。
search 用户代理应显示一个针对搜索优化的虚拟键盘。

HTMLElement/inputMode

在所有当前引擎中支持。

Firefox95+Safari12.1+Chrome66+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android79+Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

inputMode IDL 属性必须 反映 inputmode 内容属性,仅限于已知值

inputmode 未指定(或处于用户代理不支持的状态)时,用户代理应确定要显示的默认虚拟键盘。应使用上下文信息(如输入 typepattern 属性)来确定应向用户呈现哪种类型的虚拟键盘。

6.8.10 输入方式:enterkeyhint 属性

用户代理可以在表单控件(如 textarea 元素的值)或编辑宿主中的元素(例如使用 contenteditable)上支持 enterkeyhint 属性。

Global_attributes/enterkeyhint

在所有当前引擎中支持。

Firefox94+Safari13.1+Chrome77+
Opera66+Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android57+

enterkeyhint 内容属性是一个 枚举属性,它指定在虚拟键盘上为 Enter 键呈现哪个操作标签(或图标)。这允许作者自定义 Enter 键的呈现方式,使其对用户更有帮助。

关键字描述
enter 用户代理应呈现“Enter”操作的提示,通常是插入新行。
done 用户代理应呈现“Done”操作的提示,通常表示没有更多内容要输入,并且输入法编辑器 (IME) 将关闭。
go 用户代理应该提供一个操作“go”的提示,通常意味着将用户带到他们输入文本的目标位置。
next 用户代理应该提供一个操作“next”的提示,通常将用户带到下一个可以接受文本的字段。
previous 用户代理应该提供一个操作“previous”的提示,通常将用户带到上一个可以接受文本的字段。
search 用户代理应该提供一个操作“search”的提示,通常将用户带到他们输入文本的搜索结果。
send 用户代理应该提供一个操作“send”的提示,通常将文本发送到其目标。

HTMLElement/enterKeyHint

在所有当前引擎中支持。

Firefox94+Safari13.1+Chrome77+
Opera?Edge79+
旧版 Edge?Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

enterKeyHint IDL 属性必须 反映 enterkeyhint 内容属性,仅限于已知值

enterkeyhint 未指定(或处于用户代理不支持的状态)时,用户代理应确定要显示的默认操作标签(或图标)。上下文信息,例如 inputmodetypepattern 属性,应用于确定在虚拟键盘上显示哪个操作标签(或图标)。

6.9 页面内查找

6.9.1 简介

本节定义了页面内查找——一种常见的用户代理机制,允许用户在页面内容中搜索特定信息。

通过页面内查找接口提供对页面内查找功能的访问。这是一个用户代理提供的用户界面,允许用户指定输入和搜索参数。此接口可以作为快捷方式或菜单选择的结果出现。

页面内查找接口中的文本输入和设置组合表示用户查询。这通常包括用户想要搜索的文本,以及可选设置(例如,仅限于整个单词的搜索)。

用户代理处理给定查询的页面内容,并识别零个或多个匹配,这些匹配是满足用户查询的内容范围。

其中一个匹配被识别为用户的活动匹配。它被突出显示并滚动到视图中。用户可以通过使用页面内查找接口推进活动匹配来浏览匹配

问题 #3539跟踪对页面内查找的标准化,它作为目前未指定的window.find() API 的基础。

6.9.2detailshidden=until-found 的交互

当页面内查找开始搜索匹配项时,页面中所有没有设置open 属性的details 元素,它们的第二插槽的跳过内容将变得可访问,而无需修改open 属性,以便页面内查找能够搜索其中的内容。类似地,所有具有隐藏直到找到状态的hidden 属性的 HTML 元素,它们的跳过内容将变得可访问,而无需修改hidden 属性,以便页面内查找能够搜索其中的内容。在页面内查找完成匹配搜索后,details 元素和具有隐藏直到找到状态的hidden 属性的元素,它们的内容将再次变为跳过。整个过程必须同步发生(因此对用户或作者代码不可见)。[CSSCONTAIN]

当页面内查找选择新的活动匹配时,执行以下步骤

  1. node活动匹配中的第一个节点。

  2. 在给定node相关全局对象用户交互任务源 上排队一个全局任务,以运行以下步骤

    1. node 上运行祖先 details 元素揭示算法

    2. node 上运行祖先 hidden-until-found 元素揭示算法

(这是一个跟踪向量。) 当页面内查找像这样自动扩展details 元素时,它将触发toggle 事件。与页面内查找触发的单独scroll 事件一样,页面可以使用此事件来发现用户在页面内查找对话框中输入的内容。如果页面创建一个带有当前搜索词和用户可能键入的每个后续字符的小型可滚动区域,这些字符之间用间隙分隔,并观察浏览器滚动了哪个字符,它就可以将该字符添加到搜索词中,并更新可滚动区域以逐步构建搜索词。通过将每个可能的后续匹配项包装在一个封闭的details 元素中,页面可以监听toggle 事件而不是scroll 事件。这种攻击可以通过不处理用户在页面内查找对话框中键入的每个字符来解决。

6.9.3 与选择的交互

页面内查找过程是在文档的上下文中调用的,并且可能对该文档的选择产生影响。具体来说,定义活动匹配的范围可以决定当前选择。但是,这些选择更新可能在页面内查找过程中的不同时间发生(例如,在页面内查找接口关闭时或活动匹配范围发生变化时)。

6.10 关闭请求和关闭观察器

6.10.1 关闭请求

实现定义的(并且很可能是设备特定的)方式,用户可以向用户代理发送关闭请求。这表示用户希望关闭当前显示在屏幕上的某些内容,例如弹出窗口、菜单、对话框、选择器或显示模式。

一些关闭请求示例是

每当用户代理接收到针对Document document 的潜在关闭请求时,它必须在给定document相关全局对象用户交互任务源 上排队一个全局任务,以执行以下关闭请求步骤

  1. 如果document全屏元素 不为空,则

    1. 完全退出全屏,给定document节点可导航顶级可遍历活动文档

    2. 返回。

    不会触发任何相关的事件,例如keydown;它只会导致fullscreenchange 最终被触发。

  2. 可选地,跳到标记为备用处理 的步骤。

    例如,如果用户代理检测到用户因当前网页重复拦截关闭请求而感到沮丧,它可能会采取此路径。

  3. 根据UI 事件 或其他相关规范,触发任何相关的事件。 [UIEVENTS]

    UI 事件 模型中相关事件的一个例子是keydown 事件,当用户按下键盘上的 Esc 键时,UI 事件 建议 触发此事件。在大多数带有键盘的平台上,这被视为关闭请求,因此将触发这些关闭请求步骤

    例如,在UI Events中给出的模型之外的相关事件,例如辅助技术合成Esc keydown事件,当用户使用取消手势发送关闭请求时。

  4. 如果未触发此类事件,则event为null,否则为表示触发事件之一的Event对象。如果触发了多个事件,则选择哪个事件由实现定义

  5. 如果event不为null,并且其取消标志已设置,则返回。

  6. 如果document不是完全活跃的,则返回。

    此步骤是必要的,因为如果event不为null,则事件监听器可能会导致document不再完全活跃

  7. closedSomething为在document相关全局对象处理关闭观察者的结果。

  8. 如果closedSomething为true,则返回。

  9. 替代处理:否则,没有任何东西在监视关闭请求。用户代理可以将此交互解释为其他操作,而不是将其解释为关闭请求。

在按下Esc键被解释为关闭请求的平台上,用户代理必须将键按下向下解释为关闭请求,而不是键被释放。因此,在上面的算法中,触发的“相关事件”必须是单个keydown事件。

Esc键是关闭请求的平台上,用户代理将首先触发一个适当初始化的keydown事件。如果 Web 开发人员通过调用preventDefault()取消事件,则不会发生任何其他情况。但如果事件触发而未被取消,则用户代理将继续处理关闭观察者

在后退按钮是潜在的关闭请求的平台上,不涉及任何事件,因此当按下后退按钮时,用户代理将直接继续处理关闭观察者。如果有活动关闭观察者,那么它将被触发。如果没有,则用户代理可以以其他方式解释后退按钮的按下,例如作为按-1的增量遍历历史记录的请求。

6.10.2 关闭观察者基础设施

每个Window都有一个关闭观察者管理器,它是一个结构,具有以下

关闭观察者管理器的大部分复杂性来自反滥用保护,旨在防止开发人员禁用用户的历史记录遍历功能,对于那些关闭请求回退操作是历史记录遍历的主要机制的平台。特别是

关闭观察者的分组设计为,如果在没有历史记录操作激活的情况下创建了多个关闭观察者,则将它们分组在一起,以便用户触发的关闭请求将关闭组中的所有关闭观察者。这确保了 Web 开发人员无法通过创建关闭观察者来拦截无限数量的关闭请求;相反,他们可以创建的数量最多等于1+用户激活页面的次数。

下一次用户交互允许新组布尔值鼓励 Web 开发人员以与单个用户激活绑定方式创建关闭观察者。如果没有它,每次用户激活都会增加允许的组数,即使 Web 开发人员没有“使用”这些用户激活来创建关闭观察者。简而言之

这种保护对维护我们想要的不超过(1+用户激活页面的次数)个组的创建不变式很重要。一个有决心的滥用者只会为每次用户交互创建一个关闭观察者,以便“储备”它们以备将来滥用。但这种系统会导致正常情况下的行为更可预测,并鼓励非滥用开发人员直接响应用户交互来创建关闭观察者。

通知关闭观察者管理器用户激活,给定一个Windowwindow

  1. managerwindow关闭观察者管理器

  2. 如果manager下一次用户交互允许新组为true,则增加manager允许的组数

  3. manager下一次用户交互允许新组设置为false。


一个关闭观察者是一个结构,具有以下

一个关闭观察者closeWatcher处于活动状态,如果closeWatcher窗口关闭观察者管理器包含任何包含closeWatcher的列表。


建立一个关闭观察者,给定一个Windowwindow,一个步骤列表cancelAction,以及一个步骤列表closeAction

  1. 断言window关联的Document完全活跃的。

  2. closeWatcher为一个新的关闭观察者,具有

    窗口
    窗口
    取消操作
    cancelAction
    关闭操作
    closeAction
    正在运行取消操作
    false
  3. managerwindow关闭观察者管理器

  4. 如果manager大小小于manager允许的组数,则将« closeWatcher »追加manager

  5. 否则

    1. 断言manager大小在此分支中至少为1,因为manager允许的组数始终至少为1。

    2. closeWatcher追加manager的最后一个

  6. manager下一次用户交互允许新组设置为true。

  7. 返回closeWatcher

请求关闭一个关闭观察者closeWatcher

  1. 如果closeWatcher不处于活动状态,则返回true。

  2. 如果 closeWatcher正在运行取消操作 为 true,则返回 true。

  3. windowcloseWatcher窗口

  4. 如果 window关联的 Document 不是 完全活跃 的,则返回 true。

  5. canPreventClose 为 true,如果 window关闭监视器管理器大小 小于 window关闭监视器管理器允许的组数,并且 window 具有 历史操作激活;否则为 false。

  6. closeWatcher正在运行取消操作 设置为 true。

  7. shouldContinue 为运行 closeWatcher取消操作 给定 canPreventClose 的结果。

  8. closeWatcher正在运行取消操作 设置为 false。

  9. 如果 shouldContinue 为 false,则

    1. 断言canPreventClose 为 true。

    2. 消耗历史操作用户激活 给定 window

    3. 返回 false。

    请注意,由于这些子步骤 消耗历史操作用户激活请求关闭 一个 关闭监视器 两次而没有任何介入的 用户激活 将导致 canPreventClose 第二次为 false。

  10. 关闭 closeWatcher

  11. 返回 true。

关闭 一个 关闭监视器 closeWatcher

  1. 如果 closeWatcher 没有激活,则返回。

  2. 如果 closeWatcher窗口关联的 Document 不是 完全活跃 的,则返回。

  3. 销毁 closeWatcher

  4. 运行 closeWatcher关闭操作

销毁 一个 关闭监视器 closeWatcher

  1. managercloseWatcher窗口关闭监视器管理器

  2. 对于每个 manager移除 closeWatchergroup 中。

  3. 移除 manager为空 的任何项目。


处理关闭监视器 给定一个 Window window

  1. processedACloseWatcher 为 false。

  2. 如果 window关闭监视器管理器 不为空

    1. groupwindow关闭监视器管理器 中最后一个 项目

    2. 对于每个 groupcloseWatcher,以逆序

      1. processedACloseWatcher 设置为 true。

      2. shouldProceed请求关闭 closeWatcher 的结果。

      3. 如果 shouldProceed 为 false,则 中断

  3. 如果 window关闭监视器管理器允许的组数 大于 1,则将其减 1。

  4. 返回 processedACloseWatcher

6.10.3 CloseWatcher 接口

[Exposed=Window]
interface CloseWatcher : EventTarget {
  constructor(optional CloseWatcherOptions options = {});

  undefined requestClose();
  undefined close();
  undefined destroy();

  attribute EventHandler oncancel;
  attribute EventHandler onclose;
};

dictionary CloseWatcherOptions {
  AbortSignal signal;
};
watcher = new CloseWatcher()
watcher = new CloseWatcher({ signal })

创建一个新的 CloseWatcher 实例。

如果提供了 signal 选项,则可以通过中止给定的 AbortSignal 来销毁 watcher(就像通过 watcher.destroy() 一样)。

如果任何 关闭监视器 已经激活,并且 Window 没有 历史操作激活,则响应任何 关闭请求,生成的 CloseWatcher 将与该已激活的 关闭监视器 一起关闭。(该已激活的 关闭监视器 不一定必须是 CloseWatcher 对象;它可能是模态 dialog 元素,或者是由具有 popover 属性的元素生成的弹出窗口。)

watcher.requestClose()

就像发送一个针对 watcher关闭请求 一样,首先触发一个 cancel 事件,如果该事件没有通过 preventDefault() 取消,则继续触发一个 close 事件,然后停用关闭监视器,就像调用了 watcher.destroy() 一样。

这是一个辅助工具,可用于将取消和关闭逻辑整合到 cancelclose 事件处理程序中,方法是让所有非 关闭请求 关闭功能调用此方法。

watcher.close()

立即触发 close 事件,然后停用关闭监视器,就像调用了 watcher.destroy() 一样。

这是一个辅助工具,可用于触发将关闭逻辑整合到 close 事件处理程序中,跳过 cancel 事件处理程序中的任何逻辑。

watcher.destroy()

停用 watcher,以便它不再接收 close 事件,并且可以构造新的独立 CloseWatcher 实例。

如果相关 UI 元素以某种方式被拆除,而不是被关闭,则应该调用此方法。

每个 CloseWatcher 实例都有一个 内部关闭监视器,它是一个 关闭监视器

new CloseWatcher(options) 构造函数步骤为

  1. 如果 this相关全局对象关联的 Document 不是 完全活跃 的,则抛出一个 "InvalidStateError" DOMException

  2. closeWatcher建立关闭监视器 给定 this相关全局对象 的结果,其中

  3. 如果 options["signal"] 存在,则

    1. 如果 options["signal"] 为 已中止,则 销毁 closeWatcher

    2. 添加 以下步骤到 options["signal"]

      1. 销毁 closeWatcher.

  4. this内部关闭观察器 设置为 closeWatcher.

The requestClose() 方法的步骤是 请求关闭 this内部关闭观察器.

The close() 方法的步骤是 关闭 this内部关闭观察器.

The destroy() 方法的步骤是 销毁 this内部关闭观察器.

以下是所有实现 CloseWatcher 接口的对象必须支持的 事件处理程序(以及它们对应的 事件处理程序事件类型),作为 事件处理程序 IDL 属性

事件处理程序 事件处理程序事件类型
oncancel cancel
onclose close

如果想要实现一个自定义的 picker 控件,该控件在用户提供的 关闭请求 以及按下关闭按钮时关闭自身,则以下代码展示了如何使用 CloseWatcher API 来处理关闭请求

const watcher = new CloseWatcher();
const picker = setUpAndShowPickerDOMElement();

let chosenValue = null;

watcher.onclose = () => {
  chosenValue = picker.querySelector('input').value;
  picker.remove();
};

picker.querySelector('.close-button').onclick = () => watcher.requestClose();

请注意,收集选定值的逻辑集中在 CloseWatcher 对象的 close 事件处理程序中,而关闭按钮的 click 事件处理程序通过调用 requestClose() 来委托该逻辑。

The cancel event on CloseWatcher objects can be used to prevent the close event from firing, and the CloseWatcher from being destroying. A typical use case is as follows

watcher.oncancel = async (e) => {
  if (hasUnsavedData && e.cancelable) {
    e.preventDefault();

    const userReallyWantsToClose = await askForConfirmation("Are you sure you want to close?");
    if (userReallyWantsToClose) {
      hasUnsavedData = false;
      watcher.close();
    }
  }
};

为了防止滥用,此事件仅在页面具有 历史记录操作激活 时才 可取消,在任何给定的 关闭请求 之后,历史记录操作激活将丢失。这确保了如果用户在没有任何用户激活的情况下连续两次发送关闭请求,则该请求一定会成功;第二个请求会忽略任何 cancel 事件处理程序调用 preventDefault() 的尝试,并继续关闭 CloseWatcher

结合以上两个例子,展示了 requestClose()close() 的区别。因为我们在关闭按钮的 click 事件处理程序中使用了 requestClose(),所以点击该按钮会触发 CloseWatchercancel 事件,从而可能在存在未保存的数据时询问用户确认。如果我们使用了 close(),那么这个检查会被跳过。有时这很合适,但通常情况下,requestClose() 是用户触发的关闭请求的更好选择。

除了 cancel 事件的 用户激活 限制外,还有一种更微妙的 CloseWatcher 构造的用户激活门控形式。如果在没有用户激活的情况下创建了多个 CloseWatcher,那么新创建的 CloseWatcher 会与最近创建的 关闭观察器 分组,因此单个 关闭请求 会关闭这两个观察器。

window.onload = () => {
  // This will work as normal: it is the first close watcher created without user activation.
  (new CloseWatcher()).onclose = () => { /* ... */ };
};

button1.onclick = () => {
  // This will work as normal: the button click counts as user activation.
  (new CloseWatcher()).onclose = () => { /* ... */ };
};

button2.onclick = () => {
  // These will be grouped together, and both will close in response to a single close request.
  (new CloseWatcher()).onclose = () => { /* ... */ };
  (new CloseWatcher()).onclose = () => { /* ... */ };
};

这意味着正确调用 destroy()close()requestClose() 很重要。这样做是获取回“免费”未分组关闭观察器插槽的唯一方法。此类在没有用户激活的情况下创建的关闭观察器适用于会话不活动超时对话框或服务器触发的事件的紧急通知之类的用例,这些事件不是响应用户激活而生成的。