<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 2017Jan 2-8 20172017-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 表格僅在瀏覽器中載入