获取无效的html5日期输入值

时间:2017-06-20 05:23:04

标签: javascript html5 validation html5-input-date

我正在构建一个日历选择器(并将某些浏览器提供的默认日历日期选择器替换为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;
&#13;
&#13;

1 个答案:

答案 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,屏幕阅读器等必须可以访问可见值,也可以手动复制到剪贴板。

尝试了多种以编程方式选择和复制文本的方法,我已经没有想法和耐心,只能设法将其复制到剪贴板。

  • 如果其他人可以弄清楚如何使用JS阅读aria-value*的{​​{1}}属性,那么您就有了前进的方向。
  • 如果其他人可以弄明白如何将#shadow-root (user-agent)字符串分配给selection,那么您还有另一种方法。

然而

由于无效输入仅限于可预测地超出范围,因此您可以监视最后一个有效var在更改为无效之前的内容,然后计算它现在肯定是什么。

  • 如果使用日期选择器,则所有输入都有效。
  • 如果输入,请监控按键。
  • 如果使用箭头按钮,并且日期为value之前的更改无效,30/06/201729/06/201730/05/201730/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;
}