hax*_*ton 5 javascript validation html5 html5-input-date
我建立一个日历选取陪(和替换某些浏览器提供的默认日历日期选择器)的input的type="date"。
据记录,对于“简单性”,Chrome浏览器(可能还有其他浏览器)的日期输入允许输入无效的日期,但是它们将无法验证(即,可以输入2017年6月31日,但产生的“值”为“ ”)。
我的问题是:当输入无效日期时,如何获取无效日期的值?
var date_input = document.getElementById('date_input');
var output_div = document.getElementById('output_div');
output_div.innerHTML = date_input.value;
date_input.addEventListener('input', function(e){
output_div.innerHTML = e.target.value;
});Run Code Online (Sandbox Code Playgroud)
<p>To quickly input an invalid date, select the day field and press the down arrow (on Chrome OSX this displays an empty div below the input instead of the invalid date). This will select 31/06/2017</p>
<input type="date" value="2017-06-01" id="date_input" />
<br />
<br />
<div id="output_div" />Run Code Online (Sandbox Code Playgroud)
var date_input = document.getElementById( 'date_input' );
var output_div = document.getElementById( 'output_div' );
output_div.textContent = date_input.valueAsDate; // :-)
date_input.addEventListener( 'input', function( evt ){
var val = date_input.value,
sel = document.getSelection();
if ( date_input.validity.badInput ) {
// date_input.focus(); // with or without this,
// date_input.select(); // this doesn't work but,
// due to the added <span> wrapper:
sel.selectAllChildren( date_input.parentElement );
// this does. So:
val = sel.toString() || function() {
var copied = document.execCommand( 'copy' );
sel.empty(); // clear the selection
return "Invalid date" + ( copied ? " copied to clipboard." : "" );
}();
}
output_div.textContent = val;
});Run Code Online (Sandbox Code Playgroud)
#output_div {
margin-top: 1em;
}Run Code Online (Sandbox Code Playgroud)
<p>To quickly input an invalid date, select the day field and press the down arrow (on Chrome OSX this displays an empty div below the input instead of the invalid date). This will select 31/06/2017</p>
<span><input type="date" value="2017-06-01" id="date_input"></span>
<div id="output_div"></div>Run Code Online (Sandbox Code Playgroud)
显然,因为value显示的实际上是影子 DOM的输出 显示的实际上子级<input>,并且我们无法访问 的user-agent影子 DOM,因此 JS 实际上不知道可见值。
出于可访问性的原因,可见值必须可供屏幕阅读器等访问,并且还可以手动复制到剪贴板。
在尝试了多种以编程方式选择和复制文本的方法后,我已经失去了想法和耐心,只能设法将其复制到剪贴板。
aria-value*属性#shadow-root (user-agent),那么您就有了前进的方向。selection字符串分配给 a var,那么您就有了另一种方法。由于无效输入仅限于可预测的超出范围,因此您可以监视最后一个有效输入的内容value在更改为无效输入之前是什么,然后计算它现在肯定是什么。
30/06/2017导致其无效的更改之前,且29/06/2017、30/05/2017、30/07/2017和30/06/2016均30/06/2018有效,则无效日期必须为31/06/2017。我没有尝试过让它发挥作用,但我相信它可以。我会用这个答案发布这个解决方案,但是我的半天已经被这个问题吞噬了,而且我很饿。如果表达了真诚的兴趣,我将很乐意尝试提供代码。
如果使用箭头按钮创建日期,并且仅当最后日期有效时,这将显示无效日期。我也许可以找到解决办法,但正式放弃!生命太短了。
...显示的日期格式将根据用户操作系统的设置区域设置进行选择。
这将使跟踪击键变得异常重要。
然而我刚刚发现<input type="datetime-local">这可能会解决这个问题,并且可能会解决其他问题。
但试图强迫它发挥作用开始感觉就像试图在通常不适合的地方插入一个西瓜。
这是一个笨手笨脚的拼凑,几乎没有魅力,如果有人看得太仔细,它很可能会被破坏。最好的免责声明是对的;)
var date = "",
input = document.querySelector( "input" ),
output = document.querySelector( "output" ),
bits = function( d ) {
return [ d.getFullYear(), d.getMonth() + 1, d.getDate() ];
},
adjustedDate = function( o ) {
var d = new Date( date ),
b = bits( d ),
year = b[ 0 ],
month = b[ 1 ],
day = b[ 2 ];
switch ( o.i ) {
case "d": return [ year, month, ( day + o.v ) || 31 ];
case "m": return [ year, month + o.v, day ];
case "y": return [ year + o.v, month, day ];
}
},
calcDate = function() {
var ad, vd, rd;
[ { i: "d", v: 1 },
{ i: "d", v: -1 },
{ i: "m", v: 1 },
{ i: "m", v: -1 },
{ i: "y", v: 1 },
{ i: "y", v: -1 }
].forEach( ( v ) => {
ad = adjustedDate( v ).join( "-" );
vd = bits( new Date( ad ) ).join( "-" );
if ( ad !== vd ) {
rd = ad;
}
} );
return rd.split( "-" ).map( ( v ) => {
v = v.toString();
return v.length === 1 ? "0" + v : v;
} ).join( "-" ); // tired so mental
},
showDate = function() {
output.textContent = date = ( input.value || calcDate() );
};
showDate();
input.addEventListener( "input", showDate, false );Run Code Online (Sandbox Code Playgroud)
output {
margin-left: 1em;
}Run Code Online (Sandbox Code Playgroud)
<p>To quickly input an invalid date, select the day field and press the down arrow. This will select 31/06/2017 and output the desired invalid date string.</p>
<form><input type="date" value="2017-06-01"><output></output></form>Run Code Online (Sandbox Code Playgroud)