我正在构建一个日历选择器(并将某些浏览器提供的默认日历日期选择器替换为input
type="date"
。
据记载,"简单" Chrome(以及可能的其他浏览器)日期输入允许输入无效日期,但它们将无法验证(即。可以输入31/06/2017,但会生成"值" ""。)
我的问题是:当输入中输入无效日期时,如何获取无效日期的值?
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;
});

<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" />
&#13;
答案 0 :(得分:2)
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;
});
#output_div {
margin-top: 1em;
}
<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>
显然,因为显示的value
实际上是<input>
的{{3}} 孩子的输出,并且{{3但是,JS的有效值是未知的。
对于shadow DOM,屏幕阅读器等必须可以访问可见值,也可以手动复制到剪贴板。
尝试了多种以编程方式选择和复制文本的方法,我已经没有想法和耐心,只能设法将其复制到剪贴板。
aria-value*
的{{1}}属性,那么您就有了前进的方向。#shadow-root (user-agent)
字符串分配给selection
,那么您还有另一种方法。由于无效输入仅限于可预测地超出范围,因此您可以监视最后一个有效var
在更改为无效之前的内容,然后计算它现在肯定是什么。
value
之前的更改无效,30/06/2017
,29/06/2017
,30/05/2017
,30/07/2017
并且30/06/2016
都有效,无效日期必须为30/06/2018
。我已经不进行了实验,但我确信它可以做到。我会用这个答案发布那个解决方案,但已经有一半的时间被这个问题吞噬了,我很饿。如果表达了真诚的兴趣,我将很乐意尝试并提供代码。
如果使用箭头按钮创建无效日期,并且仅在最后日期有效时显示无效日期。我可能找到解决方法,但正式放弃!生命太短暂了。
we can't access the user-agent
's shadow DOM:
...将根据用户操作系统的设置区域设置选择显示的日期格式。
这会使跟踪击键变得无关紧要。
但是,我刚刚发现accessibility reasons可以解决这个问题,并且可能解决其他问题。
但是试图强迫它发挥作用开始感觉就像试图插入一个通常不会适合的西瓜。
它是一种几乎没有魅力的火腿疙瘩,如果有人看得太厉害,它很可能会破裂。最好的免责声明;)
31/06/2017
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 );
output {
margin-left: 1em;
}