【问题标题】:HTML5 <input type=“date”> - onChange EventHTML5 <input type=“date”> - onChange 事件
【发布时间】:2017-04-07 08:23:28
【问题描述】:

当用户使用图形日历和箭头或使用键盘数字时,是否可以在事件onChange 中检测到&lt;input type=“date”&gt;

我只对 VanillaJS 解决方案感兴趣。

【问题讨论】:

  • 所以问题基本上是onchange 是否正常工作?为什么不试试看呢? (如果您的意思是 onchange 是否会在用户每次更改日历中的位置但未完成编辑时触发 - 我的猜测可能不会。)
  • 好笑的是,事件只有在日期有效时才会触发。当您使用键盘时,您正在逐个构建日期。一旦日期有效,事件将开始触发。
  • 你是对的,但是日期 0002 是有效的。因此,当有人写新年(2016 年)并按第一个数字 2 时,组件被重新渲染,输入日期的新值是 0002。有人想按第二个数字(0),组件再次重​​新渲染并再次具有新值 0000。我以为当使用键盘更改日期时,这是一种检测事件对象的简单方法。我通过在 eventHandler 中进行自定义验证解决了这个问题

标签: javascript html onchange


【解决方案1】:

function elog(ev, object) {
    console.log(object.id + " - " + ev + ": " + object.value); 
}
<label for="dt1">Date not initially set: </label>
<input type="date" id="dt1" 
oninput="elog('input',this);return false;"
onchange="elog('change',this);return false;"
onblur="elog('blur',this);return false;"                     
onfocus="elog('focus',this);return false;"
onkeyup="elog('keyup-'+event.keyCode,this);return false;"
onkeypress="elog('keypress-'+event.keyCode,this);if(event.keyCode==13){this.onchange();return false;}" />

<label for="dt2">Date set to 1.12.1892 initially: </label>
<input type="date" id="dt2" 
value="1892-12-01"
oninput="elog('input',this);return false;"
onchange="elog('change',this);return false;"
onblur="elog('blur',this);return false;"                     
onfocus="elog('focus',this);return false;"
onkeyup="elog('keyup-'+event.keyCode,this);return false;"
onkeypress="elog('keypress-'+event.keyCode,this);if(event.keyCode==13){this.onchange();return false;}" />

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

通常,onchange 会在“用户提交对元素值的更改时”触发。但是对于&lt;input type='date'&gt; 字段,主要的浏览器开发人员会在他们检测到字段中的“有效”日期时立即触发onchange,即使您仍在输入。他们这样做是为了在用户从(特定于浏览器的)数据选择器/日历中选择一个值时触发onchange。基本上没有很好的方法来区分日期选择器输入的日期值和用户手动输入的日期值。

如果您使用onchange 来执行诸如提交表单之类的操作,这将是一个真正的问题。您将收到带有您不想要的值的表单提交,并且如上所述,可能是可能引发异常的错误数据(例如,“0002-04-02”是一个有效的 JS 日期,但一个无效的 SQL 日期)。

我的解决办法是这样的:

  1. 将您想要的操作绑定到onchange 事件
  2. 关于onkeypress 事件:
    1. 删除onchange 绑定
    2. 将您想要的操作绑定到onblur 事件
    3. 添加if (e.keyCode === 13) { doYourThing(); }

这意味着您的字段正确响应日期选择器中的onchange直到用户开始手动输入日期。此时,onchange 处理程序将被删除(以防止过早触发),而您改为绑定 onblur(用于切换)和 keyCode === 13(输入键)。

唯一的缺点是,如果用户开始输入日期,然后改变主意并使用数据选择器,onchange 将不会触发,并且您的操作不会发生,直到onblur 或他们按下回车键。

我知道 OP 要求纯 JS,但这是我的 jQuery 版本。

$('input[type=date]').change(function () {
    this.form.submit();
});

$('input[type=date]').keypress(function (e) {
    $(this).off('change blur');

    $(this).blur(function () {
        this.form.submit();
    });

    if (e.keyCode === 13) {
        this.form.submit();
    }
});

编辑:在重新绑定之前取消绑定 onblur 事件,这样您就不会收到多个绑定事件。

【讨论】:

  • 当用户切换回日期选择器时,是否有一种安全的方法可以重新安装 onchange 处理程序?
  • 我不知道。日期选择器都是特定于浏览器的(有些完全不同),我认为没有任何类型的“onSelect”或“onOpen”事件可以绑定。它们甚至不是 DOM 元素。我们可以检测输入字段(onKeypress)中的输入,因为该字段是一个 DOM 元素。
【解决方案3】:

function elog(ev, object) {
    console.log(object.id + " - " + ev + ": " + object.value); 
}
<label for="dt1">Date not initially set: </label>
<input type="date" id="dt1" 
oninput="elog('input',this);return false;"
onchange="elog('change',this);return false;"
onblur="elog('blur',this);return false;"					 
onfocus="elog('focus',this);return false;"
onkeyup="elog('keyup-'+event.keyCode,this);return false;"
onkeypress="elog('keypress-'+event.keyCode,this);if(event.keyCode==13){this.onchange();return false;}" />

<label for="dt2">Date set to 1.12.1892 initially: </label>
<input type="date" id="dt2" 
value="1892-12-01"
oninput="elog('input',this);return false;"
onchange="elog('change',this);return false;"
onblur="elog('blur',this);return false;"					 
onfocus="elog('focus',this);return false;"
onkeyup="elog('keyup-'+event.keyCode,this);return false;"
onkeypress="elog('keypress-'+event.keyCode,this);if(event.keyCode==13){this.onchange();return false;}" />

在确定日期选择器是否由用户完成或关闭时,我遇到了类似的问题。因此,我测试了 change、blur、select 和 focus 事件,如代码示例所示(antelove 示例的扩展)。

change 事件仅在日期选择器设置了有效日期并且值更改时才会发生。 input 事件的行为完全相同。在某些情况下,这可能会导致不良行为。当已经设置了有效日期(例如 01.12.1892)并且用户开始输入新的 4 位数年份时,在输入第一个数字后将触发更改事件(例如,1994 => 在输入第一个数字后出现更改事件'1')。如果使用后端,可能不希望将所有更改发送到服务器,而只发送最后和最终选择的日期(如果用户中止,则不发送任何内容)。

blur 事件在输入字段失去焦点时触发。这也适用于移动 safari (iOS) 上显示的日期选择器。当用户按下“完成/确定”时,会触发模糊事件,该事件可用于处理所选的最终日期。当旋转轮停止并且日期组件之一发生更改时,这里也会触发更改事件。

有趣的是,keypress 事件不会在日期组件更改时触发,但会触发 keyup 事件(即使未设置所有日期组件)。我还没有找到一种方法来提取不完整日期的当前设定值。有办法吗?

与问题无关但有用:添加按键处理程序来监听键 13(返回/回车)非常有用,当用户在网站上输入日期时,他们可以通过回车键确认日期,所以没有键盘/鼠标之间的切换是强制的。

总结: 是的,如果设置了初始日期(或在流程中设置了完整日期)并处理了更改事件,则可以查看每个日期组件的更改。当日期完成时,还可以在日期字段中跟踪用户的操作。然后可以比较以前和当前的日期值,这允许找出“光标”当前所在的位置。 我猜想跟踪左/右/上/下键是行不通的,因为不知道用户点击了哪个日期组件。

基于 Alexanders 评论的 Android

更新:似乎在 android 浏览器中,日期选择器元素仍处于选中状态,即在日期选择器关闭时处于焦点see example。在示例中,我单击了日期选择器弹出窗口中的日期,然后单击了日期选择器之外的区域。之后我单击“清除”,然后再次在日期选择器元素之外。 在所有情况下,在日期选择器之外单击(在弹出窗口关闭后)将导致触发 blur 事件。由于在所有情况下都会触发 change 事件,因此最好的方法可能是实现一个 changed 处理程序和一个 blur 处理程序来捕获这两种情况。 但要完全确定后 wimp 交互样式(如触摸)的行为,应该测试手机上的所有浏览器。如果各种移动浏览器的实现有所不同,我不会感到惊讶。

【讨论】:

  • 知道如何在日期选择器关闭时在 Android 浏览器上强制执行“模糊”事件吗?
  • @AlexanderDerck 我在带有 Android 8 和 Android 浏览器的 AVD 中对其进行了测试,似乎没有触发 blur 事件,因为在弹出窗口关闭后日期选择器仍然处于焦点。可能与移动浏览器上的触摸交互方式有关。我相应地更新了帖子。
  • 我通过检查用户代理是否与 android 相关并在触发更改事件时触发输入上的模糊事件来解决它。
  • 在使用 keyup 事件进行编辑时提取部分值,this.value 像 onkeyup="console.log('keyup-' + this.value);return false;" 一样在 Chrome 中使用。其他人的经验?
【解决方案4】:

在 YYYY-MM-DD 中格式化日期

function getObject(object)
{
//  alert(object);
//  console.log(object);
  
  console.log(object.value); // result 2019-01-03
}
&lt;input type="date" id="dt" onchange="getObject(this);"/&gt;

【讨论】:

    【解决方案5】:

    您可以使用两个事件 onchange 事件,但您的字段应首先初始化:

    var date_input = document.getElementById('date_input');
    date_input.valueAsDate = new Date();
    
    date_input.onchange = function(){
       console.log(this.value);
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <input type="date" id='date_input'>

    希望这会有所帮助。

    【讨论】:

    • 这是一个补丁。如果没有设置初始值怎么办(很常见的场景!)
    • 在输入有效日期之前无法检测到更改,因此如果未设置初始值,您只需设置有效日期(使用键盘或图形组件)即可检测到。
    • 是的!我过去也遇到过类似的情况......同时使用多个事件(keyup/onchange/oninput/click)就可以了!
    • 我之前尝试过,首先它会在您进行一次更改时多次触发该事件,其次在有效日期之前您永远不会获得该值。 (jsfiddle.net/z_acharki/jnwrc5ay/238)
    • 第二点是正确的logical,为什么要关心多次调用处理程序?是的!这是一个补丁,不是那么完美解决方案...
    【解决方案6】:

    是的,您可以检查对浏览器的支持以获取日期时间支持

    检查 bin 以获取功能示例!

    JSBin

    如果是 Chrome,除非输入整个日期,否则不会触发事件!

    【讨论】:

    • 我怀疑 OP 是否想针对那些旧浏览器(2011. - 2012.)
    【解决方案7】:

    这样的?

    function handler(e){
      alert(e.target.value);
    }
    &lt;input type="date" id="dt" onchange="handler(event);"/&gt;

    【讨论】:

      猜你喜欢
      • 2016-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 2019-04-03
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多