<input type="week">

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

¥<input> elements of type week create input fields allowing easy entry of a year plus the ISO 8601 week number during that year (i.e., week 1 to 52 or 53).

Try it

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

¥The control's user interface varies from browser to browser; cross-browser support is currently a bit limited, with only Chrome/Opera and Microsoft Edge supporting it at this time. In non-supporting browsers, the control degrades gracefully to function identically to <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

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

¥A string representing the value of the week/year entered into the input. The format of the date and time value used by this input type is described in Week strings.

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

¥You can set a default value for the input by including a value inside the value attribute, like so:

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

¥One thing to note is that the displayed format may differ from the actual value, which is always formatted yyyy-Www. When the above value is submitted to the server, for example, browsers may display it as Week 01, 2017, but the submitted value will always look like week=2017-W01.

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

¥You can also get and set the value in JavaScript using the input element's value property, for example:

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

附加属性

¥Additional attributes

除了 <input> 元素共有的属性外,周输入还提供以下属性。

¥In addition to the attributes common to <input> elements, week inputs offer the following attributes.

max

要接受的最新(时间方面)年份和周数,采用上面 部分中讨论的字符串格式。如果输入到元素中的 value 超过此值,则该元素将失败 约束验证。如果 max 属性的值不是有效的周字符串,则该元素没有最大值。

¥The latest (time-wise) year and week number, in the string format discussed in the Value section above, to accept. If the value entered into the element exceeds this, the element fails constraint validation. If the value of the max attribute isn't a valid week string, then the element has no maximum value.

该值必须大于或等于 min 属性指定的年和周。

¥This value must be greater than or equal to the year and week specified by the min attribute.

min

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

¥The earliest year and week to accept. If the value of the element is less than this, the element fails constraint validation. If a value is specified for min that isn't a valid week string, the input has no minimum value.

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

¥This value must be less than or equal to the value of the max attribute.

readonly

布尔属性,如果存在,则意味着用户无法编辑该字段。然而,它的 value 仍然可以通过 JavaScript 代码直接设置 HTMLInputElement value 属性来更改。

¥A Boolean attribute which, if present, means this field cannot be edited by the user. Its value can, however, still be changed by JavaScript code directly setting the HTMLInputElement value property.

注意:由于只读字段不能有值,因此 required 对同时指定了 readonly 属性的输入没有任何影响。

¥Note: Because a read-only field cannot have a value, required does not have any effect on inputs with the readonly attribute also specified.

step

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

¥The step attribute is a number that specifies the granularity that the value must adhere to, or the special value any, which is described below. Only values which are equal to the basis for stepping (min if specified, value otherwise, and an appropriate default value if neither of those is provided) are valid.

字符串值 any 意味着不暗示任何步进,并且允许任何值(除非其他约束,例如 minmax)。

¥A string value of any means that no stepping is implied, and any value is allowed (barring other constraints, such as min and max).

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

¥Note: When the data entered by the user doesn't adhere to the stepping configuration, the user agent may round to the nearest valid value, preferring numbers in the positive direction when there are two equally close options.

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

¥For week inputs, the value of step is given in weeks, with a scaling factor of 604,800,000 (since the underlying numeric value is in milliseconds). The default value of step is 1, indicating 1week. The default stepping base is -259,200,000, which is the beginning of the first week of 1970 ("1970-W01").

目前,还不清楚当与 week 输入一起使用时 "any" 的值对于 step 意味着什么。一旦确定该信息,我们将立即更新。

¥At this time, it's unclear what a value of "any" means for step when used with week inputs. This will be updated as soon as that information is determined.

使用周输入

¥Using week inputs

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

¥Week inputs sound convenient at first glance, since they provide an easy UI for choosing weeks, and they normalize the data format sent to the server, regardless of the user's browser or locale. However, there are issues with <input type="week"> because browser support is not guaranteed across all browsers.

我们将了解 <input type="week"> 的基本和更复杂的用法,然后提供有关缓解浏览器支持问题的建议(请参阅 处理浏览器支持)。

¥We'll look at basic and more complex uses of <input type="week">, then offer advice on mitigating the browser support issue later on (see Handling browser support).

周的基本用法

¥Basic uses of week

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

¥The simplest use of <input type="week"> involves a basic <input> and <label> element combination, as seen below:

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

控制输入大小

¥Controlling input size

<input type="week"> 不支持 size 等表单大小调整属性。你必须求助于 CSS 来满足尺码需求。

¥<input type="week"> doesn't support form sizing attributes such as size. You'll have to resort to CSS for sizing needs.

使用步骤属性

¥Using the step attribute

你应该能够使用 step 属性来改变每当递增或递减时跳跃的周数,但是它似乎对支持的浏览器没有任何影响。

¥You should be able to use the step attribute to vary the number of weeks jumped whenever they are incremented or decremented, however it doesn't seem to have any effect on supporting browsers.

验证

¥Validation

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

¥By default, <input type="week"> does not apply any validation to entered values. The UI implementations generally don't let you specify anything that isn't a valid week/year, which is helpful, but it's still possible to submit with the field empty, and you might want to restrict the range of choosable weeks.

设置最大和最小周数

¥Setting maximum and minimum weeks

你可以使用 minmax 属性来限制用户可以选择的有效周数。在以下示例中,我们设置最小值 Week 01, 2017 和最大值 Week 52, 2017

¥You can use the min and max attributes to restrict the valid weeks that can be chosen by the user. In the following example we are setting a minimum value of Week 01, 2017 and a maximum value of 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 中,生成的内容放置在表单控件内,无法有效设置样式或显示。

¥Here's the CSS used in the above example. Here we make use of the :valid and :invalid CSS properties to style the input based on whether the current value is valid. We had to put the icons on a <span> next to the input, not on the input itself, because in Chrome the generated content is placed inside the form control, and can't be styled or shown effectively.

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 之间只有几周被视为有效并且在支持浏览器中可供选择。

¥The result here is that only weeks between W01 and W52 in 2017 will be seen as valid and be selectable in supporting browsers.

使周值成为必需的

¥Making week values required

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

¥In addition you can use the required attribute to make filling in the week mandatory. As a result, supporting browsers will display an error if you try to submit an empty week field.

让我们看一个例子;在这里,我们设置了最短和最长周数,并且还设置了必填字段:

¥Let's look at an example; here we've set minimum and maximum weeks, and also made the field 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>

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

¥If you try to submit the form with no value, the browser displays an error. Try playing with the example now:

对于那些不使用支持浏览器的人来说,这是一个屏幕截图:

¥Here is a screenshot for those of you who aren't using a supporting browser:

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 并将数据直接提交到你的服务器。如果你的服务器端代码无法验证其接收到的数据,则当提交格式不正确的数据(或数据太大、类型错误等)时,可能会发生灾难。

¥Warning: HTML form validation is not a substitute for scripts that ensure that the entered data is in the proper format. It's far too easy for someone to make adjustments to the HTML that allow them to bypass the validation, or to remove it entirely. It's also possible for someone to bypass your HTML entirely and submit the data directly to your server. If your server-side code fails to validate the data it receives, disaster could strike when improperly-formatted data is submitted (or data which is too large, of the wrong type, and so forth).

处理浏览器支持

¥Handling browser support

如上所述,现在使用周输入的主要问题是浏览器支持:桌面版 Safari 和 Firefox 不支持,老版本的 IE 也不支持。

¥As mentioned above, the major problem with using week inputs right now is browser support: Safari and Firefox don't support it on desktop, and old versions of IE don't support it.

Android 和 iOS 等移动平台充分利用了此类输入类型,提供了专业的 UI 控件,使你可以在触摸屏环境中轻松选择值。例如,Android Chrome 上的 week 选择器如下所示:

¥Mobile platforms such as Android and iOS make perfect use of such input types, providing specialist UI controls that make it really easy to select values in a touchscreen environment. For example, the week picker on Chrome for Android looks like this:

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.

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

¥Non-supporting browsers gracefully degrade to a text input, but this creates problems both in terms of consistency of user interface (the presented control will be different), and data handling.

第二个问题更为严重。如前所述,使用 week 输入时,实际值始终标准化为 yyyy-Www 格式。当浏览器退回到通用文本输入时,没有任何东西可以指导用户正确格式化输入(而且这当然不直观)。人们可以通过多种方式编写周值;例如:

¥The second problem is the more serious. As mentioned earlier, with a week input the actual value is always normalized to the format yyyy-Www. When the browser falls back to a generic text input, there's nothing to guide the user toward correctly formatting the input (and it's certainly not intuitive). There are multiple ways in which people could write week values; for example:

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

目前以跨浏览器方式处理表单中的周/年的最佳方法是让用户在单独的控件中输入周数和年份(<select> 元素很流行;请参阅下面的示例),或使用 JavaScript 库,例如 jQuery 日期选择器

¥The best way to deal with week/years in forms in a cross-browser way at the moment is to get the user to enter the week number and year in separate controls (<select> elements being popular; see below for an example), or use JavaScript libraries such as jQuery date picker.

示例

¥Examples

在此示例中,我们创建两组用于选择周的 UI 元素:使用 <input type="week"> 创建的原生选择器,以及一组两个 <select> 元素,用于在不支持 week 输入类型的旧浏览器中选择周/年。

¥In this example we create two sets of UI elements for choosing weeks: a native picker created using <input type="week">, and a set of two <select> elements for choosing weeks/years in older browsers that don't support the week input type.

HTML 看起来像这样:

¥The HTML looks like so:

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 代码动态生成。

¥The week values are dynamically generated by the JavaScript code below.

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;
}

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

¥The other part of the code that may be of interest is the feature detection code. To detect whether the browser supports <input type="week">, we create a new <input> element, try setting its type to week, then immediately check what its type is set to. Non-supporting browsers will return text, because the week type falls back to type text. If <input type="week"> is not supported, we hide the native picker and show the fallback picker UI (<select>s) instead.

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 周(参见 每年几周)!开发生产应用时需要考虑到这一点。

¥Note: Remember that some years have 53 weeks in them (see Weeks per year)! You'll need to take this into consideration when developing production apps.

技术总结

¥Technical summary

代表一周和一年的字符串,或者为空
活动 changeinput
支持的通用属性 autocompletelistreadonlystep
IDL 属性 valuevalueAsDatevalueAsNumberlist
DOM 接口

HTMLInputElement

方法 select()stepDown()stepUp()
隐式 ARIA 角色 no corresponding role

规范

Specification
HTML Standard
# week-state-(type=week)

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看