jQuery HTML5 数据列表的事件,当项目被选择或输入与列表中的项目匹配时

jQuery event for HTML5 datalist when item is selected or typed input match with item in the list

我有如下数据列表 -

<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 调用。通过输入或从下拉列表中选择。

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

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

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 元素,确实没有理由不使用它。

您可以使用 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>

检查这是否适合您:

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");
})

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

简单的解决方案

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

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>

除了上面说的,我们还可以查看input的inputType,必须对应“insertReplacementText”

function textThatComesFromADatalist (event){
    const inputType = event.inputType;
    const isReplacingText = (typeof inputType === "undefined")
        || (inputType === "insertReplacementText");
    return isReplacingText;
}

function onInput(event) {
  if(textThatComesFromADatalist(event)){
    alert('selected: '+event.target.value);
  }
}
<input  oninput="onInput(event)" list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />

<datalist id="ice-cream-flavors">
    <option value="Chocolate">
    <option value="Coconut">
    <option value="Mint">
    <option value="Strawberry">
    <option value="Vanilla">
</datalist>