©
本文档使用 PHP中文网手册 发布
<input>
元素创建date
输入字段,允许轻松输入日期 - 这包括年,月和日,但不包括time
。
控件的用户界面从浏览器到浏览器都有所不同,目前支持是不完整的,请参阅浏览器兼容性以获取更多详细信息。在不受支持的浏览器中,控件会优雅地降级为简单<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
- 所显示的日期格式将根据用户浏览器的设置区域选择,而日期value
总是格式化的yyyy-mm-dd
。
您还可以使用该HTMLInputElement.value
属性在JavaScript中获取和设置日期值,例如:
var dateControl = document.querySelector('input[type="date"]');dateControl.value = '2017-06-01';
日期输入乍看起来很方便 - 它们为选择日期提供了一个简单的用户界面,并且将发送到服务器的数据格式标准化,而不管用户的区域设置如何。但是,<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月的天数可以选择-只有 "天" 部分的文本值将是可编辑的, 和日期以外的4月不能滚动到 datepicker 小部件。
注意:您应该能够使用该step
属性来改变每次增加日期时跳过的天数(例如,也许您只希望使周六可选)。但是,在编写本文的任何实施过程中,这似乎并不奏效。
<input type="date">
不支持表单大小属性,如size
。你将不得不求助于CSS的大小需求。
默认情况下,<input type="date">
不对输入的值应用任何验证。UI实现通常不会让你输入任何不是日期的东西 - 这很有帮助 - 但是你仍然可以不填写日期并提交,或者输入无效的日期(例如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>
如果您尝试提交的表单的日期不完整 (或在设置边界之外的日期), 浏览器将显示一个错误。现在尝试使用该示例:
下面是那些不使用支持浏览器的用户的截图:
这是上面例子中使用的CSS。这里我们利用:valid
和:invalid
CSS属性来根据当前值是否有效来设置输入的样式。我们必须将图标放在<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表单验证是不是脚本,确保输入的数据是正确的格式的替代品。有人很容易调整HTML,使他们绕过验证,或完全删除它。也有人可能完全绕过你的HTML,直接提交数据到你的服务器。如果您的服务器端代码无法验证接收到的数据,当格式不正确的数据被提交(或数据太大,类型错误等等)时,可能会发生灾难。
如上所述,在撰写本文时使用日期输入的主要问题是浏览器支持。举个例子,Android版Firefox的日期选择器如下所示:
不支持的浏览器会优雅地降级为文本输入,但这会在用户界面的一致性(所呈现的控件将不同)和数据处理方面造成问题。
第二个问题是最严重的 - 正如我们前面提到的,有一个日期输入,实际值总是标准化为格式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>
如果您尝试提交,则会看到浏览器现在显示一条错误消息(并将输入高亮显示为无效),如果输入与模式不匹配nnnn-nn-nn
,其中n
是从0到9的数字。当然,这不会不要阻止人们输入无效的日期,或者错误地格式化日期,例如yyyy-dd-mm
(而我们想要yyyy-mm-dd
)。所以我们仍然有一个问题。
目前以跨浏览器的方式处理表单中日期的最好方法是让用户在单独的控件(<select>
正在流行的元素 - 请参阅下面的实现)中输入日期,月份和年份,或者使用JavaScript库,如jQuery日期选择器。
在这个例子中,我们创建了两组用于选择日期的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>
月份是硬编码的(因为它们总是相同的),而日和年的值是根据当前选择的月份和年份以及当年动态生成的(请参阅下面的代码注释,了解这些函数的工作原理的详细说明。 )
该代码可能会感兴趣的另一部分是特征检测码-来检测浏览器是否支持<input type="date">
,我们创建了一个新的<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;}
规范 | 状态 | 注释 |
---|---|---|
HTML生活标准在该规范中定义了'<input type ='date'>''。 | 生活水平 | |
HTML5该规范中的<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 |