?
This document uses PHP Chinese website manual Release
<input>
元素創(chuàng)建date
輸入字段,允許輕松輸入日期 - 這包括年,月和日,但不包括time
。
控件的用戶界面從瀏覽器到瀏覽器都有所不同,目前支持是不完整的,請參閱瀏覽器兼容性以獲取更多詳細信息。在不受支持的瀏覽器中,控件會優(yōu)雅地降級為簡單<input type="text">.
<input id="date" type="date">
對于那些不使用支持瀏覽器的用戶,Chrome / Opera日期控件看起來像這樣:
和邊緣日期控件看起來像這樣:
值 | 表示日期的DOMString,或者為空 |
---|---|
活動 | 改變和輸入 |
支持的通用屬性 | 自動完成,列表,只讀和步驟 |
IDL屬性 | list,value,valueAsDate,valueAsNumber。 |
方法 | select(),stepDown(),stepUp() |
A DOMString
表示輸入到輸入中的日期的值。您可以通過在value
屬性中包含日期來為輸入設置默認值,如下所示:
<input id="date" type="date" value="2017-06-01">
有一件事要注意的是,顯示的日期格式與實際不同value
- 所顯示的日期格式將根據(jù)用戶瀏覽器的設置區(qū)域選擇,而日期value
總是格式化的yyyy-mm-dd
。
您還可以使用該HTMLInputElement.value
屬性在JavaScript中獲取和設置日期值,例如:
var dateControl = document.querySelector('input[type="date"]');dateControl.value = '2017-06-01';
日期輸入乍看起來很方便 - 它們?yōu)檫x擇日期提供了一個簡單的用戶界面,并且將發(fā)送到服務器的數(shù)據(jù)格式標準化,而不管用戶的區(qū)域設置如何。但是,<input type="date">
由于瀏覽器支持有限,因此存在問題。
我們將考慮基本的和更復雜的用途<input type="date">
,然后就減輕瀏覽器支持問題提供建議(請參閱處理瀏覽器支持)。
最簡單的使用<input type="date">
涉及基本<input>
和<label>
元素組合,如下所示:
<form> <div> <label for="bday">Enter your birthday:</label> <input type="date" id="bday" name="bday"> </div></form>
您可以使用min
和max
屬性來限制用戶可以選擇的日期。在下面的例子中,我們將最小日期2017-04-01
和最大日期設置為2017-04-30
:
<form> <div> <label for="party">Choose your preferred party date:</label> <input type="date" id="party" name="party" min="2017-04-01" max="2017-04-30"> </div></form>
這里的結果是, 只有在4月的天數(shù)可以選擇-只有 "天" 部分的文本值將是可編輯的, 和日期以外的4月不能滾動到 datepicker 小部件。
注意:您應該能夠使用該step
屬性來改變每次增加日期時跳過的天數(shù)(例如,也許您只希望使周六可選)。但是,在編寫本文的任何實施過程中,這似乎并不奏效。
<input type="date">
不支持表單大小屬性,如size
。你將不得不求助于CSS的大小需求。
默認情況下,<input type="date">
不對輸入的值應用任何驗證。UI實現(xiàn)通常不會讓你輸入任何不是日期的東西 - 這很有幫助 - 但是你仍然可以不填寫日期并提交,或者輸入無效的日期(例如4月32日)。
如果您使用min
和max
限制可用日期(請參閱anch(“設置最大值和最小值日期”)),如果您嘗試提交超出設定范圍的日期,支持的瀏覽器將顯示錯誤。
此外, 您還可以使用required
屬性來強制填寫日期, 如果您嘗試提交空日期字段, 則會顯示錯誤。
讓我們看一個例子-在這里, 我們已經設置了最小和最大的日期:
<form> <div> <label for="party">Choose your preferred party date (required, April 1st to 20th):</label> <input type="date" id="party" name="party" min="2017-04-01" max="2017-04-20" required> <span class="validity"></span> </div> <div> <input type="submit"> </div></form>
如果您嘗試提交的表單的日期不完整 (或在設置邊界之外的日期), 瀏覽器將顯示一個錯誤。現(xiàn)在嘗試使用該示例:
下面是那些不使用支持瀏覽器的用戶的截圖:
這是上面例子中使用的CSS。這里我們利用:valid
和:invalid
CSS屬性來根據(jù)當前值是否有效來設置輸入的樣式。我們必須將圖標放在<span>
輸入旁邊,而不是輸入本身,因為在Chrome中生成的內容放置在表單控件中,無法有效地進行樣式化或顯示。
div { margin-bottom: 10px; display: flex; align-items: center;}label { display: inline-block; width: 300px;}input:invalid+span:after { content: '?'; padding-left: 5px;}input:valid+span:after { content: '?'; padding-left: 5px;}
重要提示:HTML表單驗證是不是腳本,確保輸入的數(shù)據(jù)是正確的格式的替代品。有人很容易調整HTML,使他們繞過驗證,或完全刪除它。也有人可能完全繞過你的HTML,直接提交數(shù)據(jù)到你的服務器。如果您的服務器端代碼無法驗證接收到的數(shù)據(jù),當格式不正確的數(shù)據(jù)被提交(或數(shù)據(jù)太大,類型錯誤等等)時,可能會發(fā)生災難。
如上所述,在撰寫本文時使用日期輸入的主要問題是瀏覽器支持。舉個例子,Android版Firefox的日期選擇器如下所示:
不支持的瀏覽器會優(yōu)雅地降級為文本輸入,但這會在用戶界面的一致性(所呈現(xiàn)的控件將不同)和數(shù)據(jù)處理方面造成問題。
第二個問題是最嚴重的 - 正如我們前面提到的,有一個日期輸入,實際值總是標準化為格式yyyy-mm-dd
。另一方面,在輸入文本的情況下,瀏覽器默認不知道日期的格式,人們寫日期的方式很多,例如:
ddmmyyyy
dd/mm/yyyy
mm/dd/yyyy
dd-mm-yyyy
mm-dd-yyyy
解決這個問題的一個方法是pattern
在日期輸入中添加一個屬性。即使日期輸入不使用它,文本輸入后備將會。例如,請嘗試在不支持的瀏覽器中查看以下示例:
<form> <div> <label for="bday">Enter your birthday:</label> <input type="date" id="bday" name="bday" required pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> <span class="validity"></span> </div> <div> <input type="submit"> </div></form>
如果您嘗試提交,則會看到瀏覽器現(xiàn)在顯示一條錯誤消息(并將輸入高亮顯示為無效),如果輸入與模式不匹配nnnn-nn-nn
,其中n
是從0到9的數(shù)字。當然,這不會不要阻止人們輸入無效的日期,或者錯誤地格式化日期,例如yyyy-dd-mm
(而我們想要yyyy-mm-dd
)。所以我們仍然有一個問題。
目前以跨瀏覽器的方式處理表單中日期的最好方法是讓用戶在單獨的控件(<select>
正在流行的元素 - 請參閱下面的實現(xiàn))中輸入日期,月份和年份,或者使用JavaScript庫,如jQuery日期選擇器。
在這個例子中,我們創(chuàng)建了兩組用于選擇日期的UI元素 - 一個本機<input type="date">
選取器,以及一組三個<select>
元素,用于在舊版瀏覽器中選擇不支持本機輸入的日期。
HTML看起來像這樣:
<form> <div class="nativeDatePicker"> <label for="bday">Enter your birthday:</label> <input type="date" id="bday" name="bday"> <span class="validity"></span> </div> <p class="fallbackLabel">Enter your birthday:</p> <div class="fallbackDatePicker"> <span> <label for="day">Day:</label> <select id="day" name="day"> </select> </span> <span> <label for="month">Month:</label> <select id="month" name="month"> <option selected>January</option> <option>February</option> <option>March</option> <option>April</option> <option>May</option> <option>June</option> <option>July</option> <option>August</option> <option>September</option> <option>October</option> <option>November</option> <option>December</option> </select> </span> <span> <label for="year">Year:</label> <select id="year" name="year"> </select> </span> </div></form>
月份是硬編碼的(因為它們總是相同的),而日和年的值是根據(jù)當前選擇的月份和年份以及當年動態(tài)生成的(請參閱下面的代碼注釋,了解這些函數(shù)的工作原理的詳細說明。 )
該代碼可能會感興趣的另一部分是特征檢測碼-來檢測瀏覽器是否支持<input type="date">
,我們創(chuàng)建了一個新的<input>
元素,設置其type
到date
,然后立即檢查什么的類型設置為-不支持的瀏覽器將返回text
,因為這個date
類型會回到類型text
。如果<input type="date">
不支持,我們隱藏本地選擇器并顯示后備選取器UI(<select>
)。
// define variablesvar nativePicker = document.querySelector('.nativeDatePicker');var fallbackPicker = document.querySelector('.fallbackDatePicker');var fallbackLabel = document.querySelector('.fallbackLabel');var yearSelect = document.querySelector('#year');var monthSelect = document.querySelector('#month');var daySelect = document.querySelector('#day');// hide fallback initiallyfallbackPicker.style.display = 'none';fallbackLabel.style.display = 'none';// test whether a new date input falls back to a text input or notvar test = document.createElement('input');test.type = 'date';// if it does, run the code inside the if() {} blockif(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 days and years dynamically // (the months are always the same, therefore hardcoded) populateDays(monthSelect.value); populateYears();}function populateDays(month) { // delete the current set of <option> elements out of the // day <select>, ready for the next set to be injected while(daySelect.firstChild){ daySelect.removeChild(daySelect.firstChild); } // Create variable to hold new number of days to inject var dayNum; // 31 or 30 days? if(month === 'January' | month === 'March' | month === 'May' | month === 'July' | month === 'August' | month === 'October' | month === 'December') { dayNum = 31; } else if(month === 'April' | month === 'June' | month === 'September' | month === 'November') { dayNum = 30; } else { // If month is February, calculate whether it is a leap year or not var year = yearSelect.value; (year - 2016) % 4 === 0 ? dayNum = 29 : dayNum = 28; } // inject the right number of new <option> elements into the day <select> for(i = 1; i <= dayNum; i++) { var option = document.createElement('option'); option.textContent = i; daySelect.appendChild(option); } // if previous day has already been set, set daySelect's value // to that day, to avoid the day jumping back to 1 when you // change the year if(previousDay) { daySelect.value = previousDay; // If the previous day was set to a high number, say 31, and then // you chose a month with less total days in it (e.g. February), // this part of the code ensures that the highest day available // is selected, rather than showing a blank daySelect if(daySelect.value === "") { daySelect.value = previousDay - 1; } if(daySelect.value === "") { daySelect.value = previousDay - 2; } if(daySelect.value === "") { daySelect.value = previousDay - 3; } }}function populateYears() { // get this year as a number var date = new Date(); var year = date.getFullYear(); // Make this year, and the 100 years before it available in the year <select> for(var i = 0; i <= 100; i++) { var option = document.createElement('option'); option.textContent = year-i; yearSelect.appendChild(option); }}// when the month or year <select> values are changed, rerun populateDays()// in case the change affected the number of available daysyearSelect.onchange = function() { populateDays(monthSelect.value);}monthSelect.onchange = function() { populateDays(monthSelect.value);}//preserve day selectionvar previousDay;// update what day has been set to previously// see end of populateDays() for usagedaySelect.onchange = function() { previousDay = daySelect.value;}
規(guī)范 | 狀態(tài) | 注釋 |
---|---|---|
HTML生活標準在該規(guī)范中定義了'<input type ='date'>''。 | 生活水平 | |
HTML5該規(guī)范中的<input type =“date”>“的定義。 | 建議 |
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 20 | 12 | No support1 | No support | 10.62 | No support2 |
Feature | Android | Chrome for Android | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|---|
Basic support | (Yes) | (Yes) | (Yes) | (Yes) | ? | 10.62 | 5 |