<input type="week">

类型为 **week** 的 <input> 元素创建输入字段,允许轻松输入年份以及该年份的 ISO 8601 周数(即,第 1 周到 第 52 或 53 周)。

试一试

控件的用户界面因浏览器而异;跨浏览器支持目前有些受限,目前只有 Chrome/Opera 和 Microsoft Edge 支持它。在不支持的浏览器中,控件会优雅地降级,功能与 <input type="text"> 相同。

An input reading 'week 01, 2017'. The background of the 2017 is the same blue as the focus ring. There are 3 icons in the input: x or clear, a spinner with small up and down arrows, and a larger down arrow. A calendar is a pop-up below the input set to January 2017. The first column of the calendar is the week: 52, 1, 2, 3, 4, 5. the full month calendar is to the right of that. The row with Week 1 and January 2 to 8 is highlighted. On the same line as the month, there are buttons to move right and left for the next and previous months.

一个字符串,表示输入的周/年值。此输入类型使用的日期和时间值的格式在 周字符串 中描述。

您可以通过在 `value` 属性中包含一个值来设置输入的默认值,如下所示

html
<label for="week">What week would you like to start?</label>
<input id="week" type="week" name="week" value="2017-W01" />

需要注意的是,显示的格式可能与实际的 value 不同,实际的 value 始终以 yyyy-Www 格式显示。例如,当上述值提交到服务器时,浏览器可能会将其显示为 Week 01, 2017,但提交的值始终像 week=2017-W01 一样。

您也可以使用输入元素的 `value` 属性在 JavaScript 中获取和设置值,例如

js
const weekControl = document.querySelector('input[type="week"]');
weekControl.value = "2017-W45";

其他属性

除了 <input> 元素的通用属性外,星期输入还提供以下属性。

max

最新的(按时间顺序)年份和星期数,以字符串格式显示,如上述 `Value` 部分所述,以接受。如果输入到元素中的 `value` 超过此值,则元素将无法通过 约束验证。如果 max 属性的值不是有效的星期字符串,则元素没有最大值。

此值必须大于或等于 min 属性指定的年份和星期。

min

接受的最早年份和星期。如果元素的 `value` 小于此值,则元素将无法通过 约束验证。如果为 min 指定的值不是有效的星期字符串,则输入没有最小值。

此值必须小于或等于 max 属性的值。

readonly

如果存在,则表示此字段无法由用户编辑的布尔属性。但是,它的 value 仍然可以通过直接设置 `HTMLInputElement` value 属性的 JavaScript 代码更改。

注意:因为只读字段不能有值,所以 required 对也指定了 readonly 属性的输入没有任何影响。

step

step 属性是一个数字,指定了值必须遵循的粒度,或者特殊值 any,如下所述。只有等于步进基础的值(如果指定了 `min`,则为 `value`,否则为适当的默认值,如果两者都没有提供,则为适当的默认值)才是有效的。

any 的字符串值表示没有隐含的步进,任何值都是允许的(除了其他约束,如 `min` 和 `max`)。

注意:当用户输入的数据不符合步进配置时,用户代理 可能四舍五入到最接近的有效值,在有两个同样接近的选项时,优先考虑正方向的数字。

对于 week 输入,step 的值以星期为单位,缩放因子为 604,800,000(因为底层的数值是以毫秒为单位的)。step 的默认值为 1,表示 1 星期。默认步进基值为 -259,200,000,即 1970 年第一周的开始("1970-W01")。

目前尚不清楚在 week 输入中使用时,"any" 的值对于 step 意味着什么。一旦确定此信息,我们将更新它。

使用周输入

星期输入乍一看很方便,因为它们提供了一种简单的 UI 来选择星期,并且它们将发送到服务器的数据格式标准化,无论用户的浏览器或区域设置如何。但是,<input type="week"> 存在一些问题,因为并非所有浏览器都保证支持它。

我们将研究 <input type="week"> 的基本和更复杂的使用方法,然后提供一些关于如何减轻浏览器支持问题的建议(参见 `Handling browser support`)。

星期的基本用法

<input type="week"> 的最简单用法涉及基本的 <input> 和 `<label>` 元素组合,如下所示

html
<form>
  <label for="week">What week would you like to start?</label>
  <input id="week" type="week" name="week" />
</form>

控制输入大小

<input type="week"> 不支持诸如 `size` 之类的表单大小属性。您需要使用 `CSS` 来满足大小需求。

使用 step 属性

您应该能够使用 `step` 属性来改变每次增量或减量时跳过的星期数,但是它似乎对支持的浏览器没有任何影响。

验证

默认情况下,<input type="week"> 不会对输入的值进行任何验证。UI 实现通常不允许您指定任何不是有效的星期/年份的内容,这很有帮助,但仍然可以提交空的字段,您可能希望限制可选择的星期范围。

设置最大和最小星期

您可以使用 `min` 和 `max` 属性来限制用户可以选择有效的星期。在下面的示例中,我们将最小值设置为 Week 01, 2017,最大值设置为 Week 52, 2017

html
<form>
  <label for="week">What week would you like to start?</label>
  <input id="week" type="week" name="week" min="2017-W01" max="2017-W52" />
  <span class="validity"></span>
</form>

以下是上述示例中使用的 CSS。在这里,我们利用 `:valid` 和 `:invalid` CSS 属性根据当前值是否有效来对输入进行样式设置。我们必须将图标放在输入旁边的 `<span>` 上,而不是输入本身,因为在 Chrome 中,生成的 content 被放置在表单控件内,无法有效地进行样式设置或显示。

css
div {
  margin-bottom: 10px;
  position: relative;
}

input[type="number"] {
  width: 100px;
}

input + span {
  padding-right: 30px;
}

input:invalid + span::after {
  position: absolute;
  content: "✖";
  padding-left: 5px;
}

input:valid + span::after {
  position: absolute;
  content: "✓";
  padding-left: 5px;
}

这里的结果是,只有 2017 年的 W01 和 W52 之间的星期将被视为有效,并且可以在支持的浏览器中进行选择。

使星期值成为必需的

此外,您可以使用 `required` 属性来使填写星期成为强制性的。因此,如果尝试提交空的星期字段,支持的浏览器将显示错误。

让我们看一个例子;这里我们设置了最小和最大星期,也使字段成为必需的

html
<form>
  <div>
    <label for="week">What week would you like to start?</label>
    <input
      id="week"
      type="week"
      name="week"
      min="2017-W01"
      max="2017-W52"
      required />
    <span class="validity"></span>
  </div>
  <div>
    <input type="submit" value="Submit form" />
  </div>
</form>

如果尝试提交没有值的表单,浏览器将显示错误。现在尝试使用该示例。

以下是在没有使用支持浏览器的用户看到截图。

The week form control has two dashes where the week number should be. A popup with a yellow warning symbol and a 'Please fill out this field' is emanating from the two dashes, which are highlighted in blue, the same blue as the input's focus ring.

警告:HTML 表单验证不是替代确保输入数据格式正确的脚本。有人很容易对 HTML 进行调整,从而使他们能够绕过验证,或者完全删除它。也可以有人完全绕过您的 HTML,并将数据直接提交到您的服务器。如果您的服务器端代码未能验证它接收到的数据,当提交格式不正确的数据(或大小过大、类型错误等数据)时,可能会发生灾难。

处理浏览器支持

如上所述,目前使用星期输入的主要问题是浏览器支持:Safari 和 Firefox 在桌面端不支持它,旧版本的 IE 也不支持它。

Android 和 iOS 等移动平台完美地利用了这些输入类型,提供了专门的 UI 控件,使其在触摸屏环境中非常容易选择值。例如,Chrome for Android 上的 week 选择器看起来像这样

A modal popup. The header reads 'set week'. There are two columns: the left has 36 in the middle at full opacity, with 35 above it and 37 below being semi-opaque. On the right side, 2017 is fully opaque. There are no other options. Three text links or buttons on the bottom include 'clear' on the 'left' and 'cancel' and 'set' on the right.

不支持的浏览器会优雅地降级为文本输入,但这会在用户界面一致性(呈现的控件将不同)和数据处理方面造成问题。

第二个问题更为严重。如前所述,对于 week 输入,实际值始终被规范化为 yyyy-Www 格式。当浏览器回退到通用文本输入时,没有任何内容可以指导用户正确地格式化输入(当然也不直观)。人们可以用多种方式来编写星期值;例如

  • Week 1 2017
  • Jan 2-8 2017
  • 2017-W01
  • 等等。

目前,在表单中以跨浏览器的方式处理星期/年份的最佳方法是让用户在单独的控件中输入星期数和年份(`<select>` 元素很受欢迎;请参见下面的示例),或者使用 JavaScript 库,如 jQuery date picker

示例

在这个示例中,我们创建了两组用于选择星期的 UI 元素:一组是使用 <input type="week"> 创建的原生选择器,另一组是两个 `<select>` 元素,用于在不支持 week 输入类型的旧浏览器中选择星期/年份。

HTML 代码如下

html
<form>
  <div class="nativeWeekPicker">
    <label for="week">What week would you like to start?</label>
    <input
      id="week"
      type="week"
      name="week"
      min="2017-W01"
      max="2018-W52"
      required />
    <span class="validity"></span>
  </div>
  <p class="fallbackLabel">What week would you like to start?</p>
  <div class="fallbackWeekPicker">
    <div>
      <span>
        <label for="week">Week:</label>
        <select id="fallbackWeek" name="week"></select>
      </span>
      <span>
        <label for="year">Year:</label>
        <select id="year" name="year">
          <option value="2017" selected>2017</option>
          <option value="2018">2018</option>
        </select>
      </span>
    </div>
  </div>
</form>

星期值由下面的 JavaScript 代码动态生成。

代码中另一个可能引起兴趣的部分是特征检测代码。为了检测浏览器是否支持 <input type="week">,我们创建一个新的 `<input>` 元素,尝试将其 type 设置为 week,然后立即检查其 type 设置为何值。不支持的浏览器将返回 text,因为 week 类型会回退到 text 类型。如果 <input type="week"> 不受支持,我们将隐藏原生选择器,并显示回退选择器 UI(`<select>`)代替。

js
// Get UI elements
const nativePicker = document.querySelector(".nativeWeekPicker");
const fallbackPicker = document.querySelector(".fallbackWeekPicker");
const fallbackLabel = document.querySelector(".fallbackLabel");

const yearSelect = document.querySelector("#year");
const weekSelect = document.querySelector("#fallbackWeek");

// Hide fallback initially
fallbackPicker.style.display = "none";
fallbackLabel.style.display = "none";

// Test whether a new date input falls back to a text input or not
const test = document.createElement("input");

try {
  test.type = "week";
} catch (e) {
  console.log(e.description);
}

// If it does, run the code inside the if () {} block
if (test.type === "text") {
  // Hide the native picker and show the fallback
  nativePicker.style.display = "none";
  fallbackPicker.style.display = "block";
  fallbackLabel.style.display = "block";

  // populate the weeks dynamically
  populateWeeks();
}

function populateWeeks() {
  // Populate the week select with 52 weeks
  for (let i = 1; i <= 52; i++) {
    const option = document.createElement("option");
    option.textContent = i < 10 ? `0${i}` : i;
    weekSelect.appendChild(option);
  }
}

注意:请记住,有些年份有 53 周(参见 Weeks per year)!在开发生产应用程序时,您需要考虑这一点。

技术摘要

表示星期和年份的字符串,或为空
事件 changeinput
支持的通用属性 autocompletelistreadonlystep
IDL 属性 listvaluevalueAsDatevalueAsNumber
DOM 接口

HTMLInputElement

方法 select()stepDown(),和 stepUp()
隐式 ARIA 角色 没有对应的角色

规范

规范
HTML 标准
# week-state-(type=week)

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅