【问题标题】:jQuery event for HTML5 datalist when item is selected or typed input match with item in the list选择项目或键入输入与列表中的项目匹配时 HTML5 数据列表的 jQuery 事件
【发布时间】:2015-07-21 00:15:36
【问题描述】:

我有如下数据列表 -

<input id="name" list="allNames" />
<datalist id="allNames">
    <option value="Adnan1"/>  
    <option value="Faizan2"/>   
</datalist>

我想要的是,当一个项目被完全输入(例如当用户完全输入“Adnan1”时在输入框中说)或从列表中选择时,我想要一个事件。我尝试了几种方法,但到目前为止都没有帮助我。方法是 -

$("#name").change(function(){
console.log("change");
}

问题在于,该事件仅在输入失去焦点时触发,即当我单击屏幕中的某个位置时。

我也试过了

$("#name").bind('change', function () {
    console.log('changed'); 
});

但是每次我输入时都会触发回调。我实际上需要在完全选择项目时进行 AJAX 调用。通过输入或从下拉列表中选择。

第一种方法不利于用户的视角,因为他必须进行额外的点击,第二种方法的缺点是每个字母都会触发一个事件。

我想要的只是用户做出选择或输入完整句子时的事件。有没有办法做到这一点?我错过的任何可以解决我的问题的事件。

【问题讨论】:

  • 不是刻薄,但并非所有浏览器都支持 HTML5 Datalist

标签: javascript jquery html jquery-events


【解决方案1】:

modern browsers,你可以使用input事件,例如:

$("#name").on('input', function () {
    var val = this.value;
    if($('#allNames option').filter(function(){
        return this.value.toUpperCase() === val.toUpperCase();        
    }).length) {
        //send ajax request
        alert(this.value);
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<input id="name" list="allNames" />
<datalist id="allNames">
    <option value="Adnan1" />
    <option value="Faizan2" />
</datalist>

PS:由于input事件的支持比datalist元素更好,如果你已经在使用datalist元素,确实没有理由不使用它。

【讨论】:

  • 当您的选项具有相似的值(一个选项可能是另一个选项的子字符串)或数字时,这会导致问题,并且多个选项可能适合结果。 IE。 1 和 10 作为选项永远不会起作用,因为您无法键入 10。一旦输入 1,就会选择该选项。本和本杰明是另一个例子。
  • @AndrewStalker 我不确定您是否在每个浏览器上看到这种行为,但据我了解您的评论,它在 chrome 上按预期工作。您描述的问题可能是因为alert() 的模态行为(safari 会受到它的影响 AFAIK)。您可以使用控制台进行测试吗:jsfiddle.net/bsyo2vdo/384 您是否面临同样的问题?如果还是这样,你能告诉我如何准确地复制这个问题吗?
  • 是的,控制台输出(在 Chrome 上)仍然会发生这种情况。使用您的 jsfiddle,只要我输入 1,控制台就会记录 1。如果您打算输入 10,那么 IRL 现在为时已晚,因为 ajax 事件已为 1 触发。
  • @AndrewStalker 好的,我明白你的意思了。通常,为了处理这种行为情况,如果仍然键入例如jsfiddle.net/bsyo2vdo/385,我们会消除 ajax 请求以让用户有足够的时间,但它似乎不是一个很好的解决方案。如果datalist 可以处理鼠标事件会更简单,但在 chrome 上却不是这样。当我有更多时间时,我会尝试找到更好的方法,但我真的不确定我能找到任何方法,不幸的是......
  • 啊,我明白了,这是有道理的。谢谢
【解决方案2】:

你可以使用input事件来实现这样的功能,如下:

$(document).ready(function() {
  $('#name').on('input', function() {
    var userText = $(this).val();

    $("#allNames").find("option").each(function() {
      if ($(this).val() == userText) {
        alert("Make Ajax call here.");
      }
    })
  })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="name" list="allNames" />
<datalist id="allNames">
  <option value="Adnan1" />
  <option value="Faizan2" />
</datalist>

【讨论】:

  • 如果从下拉列表中选择项目,则不会触发
  • @A.Wolff 看来,input 甚至是唯一的办法呢?
  • 不确定,但我猜你,因为例如在 chrome 上(不知道其他浏览器),你不能将事件绑定到 datalist 元素。现在它可能有一些肮脏的解决方法,但是......
  • 这是一个错误的解决方法,会导致某些输入数据集出错。例如,如果您有一个包含四个名称的列表,“Fred”、“Freddy”、“Fredman”,并且用户想要输入“Fredman”,它将在输入前四个字符后提交,因为它匹配“Fred” .
【解决方案3】:

简单的解决方案

document.getElementById('name').addEventListener('input', function () {
   console.log('changed'); 
});

【讨论】:

    【解决方案4】:

    Hacky 是一种罪过,但对我有用。 (请注意,如果您输入的是“Rum-Cola”,它不会在“Rum”选项上停止)

    const opts = $("option").map(function(){return  this.value;}).get();
    
    $("#favourite-drink").on("keydown", function(e){
      if(e.key){ // in case of mouse event e.key is 'undefined'
        if (e.key === "Enter") { // looks like user wants to confirm the choice
          if(opts.indexOf(this.value) >= 0){
            this.blur();
            console.log("Selected: " + this.value);
          }
        }
        else {
          this.setAttribute("data-keyboardinput", "true"); // remember that it's keyboard event
    
          setTimeout(function(){ //and keep it in memory for 100ms
            this.removeAttribute("data-keyboardinput")
          }.bind(this), 100);
        }
      }
    });
    
    $("#favourite-drink").on("input", function(){
      if(!this.dataset.keyboardinput && opts.indexOf(this.value) >= 0){ // if it's not a key press followed event
        console.log("Selected: " + this.value);
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <p>Choose a drink:</p>
      <input id="favourite-drink" list="drinks">
      <datalist id="drinks">
        <option value="Rum"></option>
        <option value="Rum-Cola"></option>
        <option value="Vodka"></option>
      </datalist>

    【讨论】:

      【解决方案5】:

      检查这是否适合您:

      var dataList=[];
      $("#allNames").find("option").each(function(){dataList.push($(this).val())})
      console.log(dataList);
      $("#name").on("keyup focus blur change",function(){
          if(dataList.indexOf($(this).val())!=-1)
      console.log("change");
      })
      

      我将 datalist 选项推送到数组中,并在更改事件 keyup 、 blur 或 focus 时,检查输入值是否存在于我的 datalist 数组中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-06
        • 2013-04-05
        • 1970-01-01
        • 2017-05-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多