<input type="week">
类型为 **week
** 的 <input>
元素创建输入字段,允许轻松输入年份以及该年份的 ISO 8601 周数(即,第 1 周到 第 52 或 53 周)。
试一试
控件的用户界面因浏览器而异;跨浏览器支持目前有些受限,目前只有 Chrome/Opera 和 Microsoft Edge 支持它。在不支持的浏览器中,控件会优雅地降级,功能与 <input type="text">
相同。
值
一个字符串,表示输入的周/年值。此输入类型使用的日期和时间值的格式在 周字符串 中描述。
您可以通过在 `value
` 属性中包含一个值来设置输入的默认值,如下所示
<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 中获取和设置值,例如
const weekControl = document.querySelector('input[type="week"]');
weekControl.value = "2017-W45";
其他属性
除了 <input>
元素的通用属性外,星期输入还提供以下属性。
max
min
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>
` 元素组合,如下所示
<form>
<label for="week">What week would you like to start?</label>
<input id="week" type="week" name="week" />
</form>
控制输入大小
使用 step 属性
您应该能够使用 `step
` 属性来改变每次增量或减量时跳过的星期数,但是它似乎对支持的浏览器没有任何影响。
验证
默认情况下,<input type="week">
不会对输入的值进行任何验证。UI 实现通常不允许您指定任何不是有效的星期/年份的内容,这很有帮助,但仍然可以提交空的字段,您可能希望限制可选择的星期范围。
设置最大和最小星期
您可以使用 `min
` 和 `max
` 属性来限制用户可以选择有效的星期。在下面的示例中,我们将最小值设置为 Week 01, 2017
,最大值设置为 Week 52, 2017
<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 被放置在表单控件内,无法有效地进行样式设置或显示。
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
` 属性来使填写星期成为强制性的。因此,如果尝试提交空的星期字段,支持的浏览器将显示错误。
让我们看一个例子;这里我们设置了最小和最大星期,也使字段成为必需的
<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>
如果尝试提交没有值的表单,浏览器将显示错误。现在尝试使用该示例。
以下是在没有使用支持浏览器的用户看到截图。
警告:HTML 表单验证不是替代确保输入数据格式正确的脚本。有人很容易对 HTML 进行调整,从而使他们能够绕过验证,或者完全删除它。也可以有人完全绕过您的 HTML,并将数据直接提交到您的服务器。如果您的服务器端代码未能验证它接收到的数据,当提交格式不正确的数据(或大小过大、类型错误等数据)时,可能会发生灾难。
处理浏览器支持
如上所述,目前使用星期输入的主要问题是浏览器支持:Safari 和 Firefox 在桌面端不支持它,旧版本的 IE 也不支持它。
Android 和 iOS 等移动平台完美地利用了这些输入类型,提供了专门的 UI 控件,使其在触摸屏环境中非常容易选择值。例如,Chrome for Android 上的 week
选择器看起来像这样
不支持的浏览器会优雅地降级为文本输入,但这会在用户界面一致性(呈现的控件将不同)和数据处理方面造成问题。
第二个问题更为严重。如前所述,对于 week
输入,实际值始终被规范化为 yyyy-Www
格式。当浏览器回退到通用文本输入时,没有任何内容可以指导用户正确地格式化输入(当然也不直观)。人们可以用多种方式来编写星期值;例如
Week 1 2017
Jan 2-8 2017
2017-W01
- 等等。
目前,在表单中以跨浏览器的方式处理星期/年份的最佳方法是让用户在单独的控件中输入星期数和年份(`<select>
` 元素很受欢迎;请参见下面的示例),或者使用 JavaScript 库,如 jQuery date picker。
示例
在这个示例中,我们创建了两组用于选择星期的 UI 元素:一组是使用 <input type="week">
创建的原生选择器,另一组是两个 `<select>
` 元素,用于在不支持 week
输入类型的旧浏览器中选择星期/年份。
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>
`)代替。
// 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)!在开发生产应用程序时,您需要考虑这一点。
技术摘要
规范
规范 |
---|
HTML 标准 # week-state-(type=week) |
浏览器兼容性
BCD 表格仅在浏览器中加载