<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 表格僅在瀏覽器中載入

另請參閱