28

我正在使用一个<datalist>

<datalist id="items"></datalist>

并使用 AJAX 填充列表

 function callServer (input) {
    xmlhttp = new XMLHttpRequest();
    xmlhttp.onreadystatechange = function(){
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
            //return the JSON object
            console.log(xmlhttp.responseText);
            var arr = JSON.parse(xmlhttp.responseText);
            var parentDiv = document.getElementById('items');
            parentDiv.innerHTML = "";
            //fill the options in the document
            for(var x = 0; x < arr.length; x++) {
                var option = document.createElement('option');
                option.value = arr[x][0];
                option.innerHTML = arr[x][1];
                //add each autocomplete option to the 'list'
                option.addEventListener("click", function() {
                  console.log("Test");
                });
                parentDiv.appendChild(option);
            };

        }
    }
    xmlhttp.open("GET", "incl/search.php?value="+input.value, true);
    xmlhttp.send();
}

但是,当我单击数据列表中的选择时,我无法让它执行操作,例如,如果我输入“Ref F”并且出现“Ref flowers”项目,如果我单击它我需要执行一个事件。

我怎样才能做到这一点?

option.addEventListener("click", function() {
option.addEventListener("onclick", function() {
option.addEventListener("change", function() {
4

7 回答 7

46

很抱歉挖掘了这个问题,但我遇到了类似的问题并且有一个解决方案,它也应该对你有用。

function onInput() {
    var val = document.getElementById("input").value;
    var opts = document.getElementById('dlist').childNodes;
    for (var i = 0; i < opts.length; i++) {
      if (opts[i].value === val) {
        // An item was selected from the list!
        // yourCallbackHere()
        alert(opts[i].value);
        break;
      }
    }
  }
<input type='text' oninput='onInput()' id='input' list='dlist' />

<datalist id='dlist'>
  <option value='Value1'>Text1</option>
  <option value='Value2'>Text2</option>
</datalist>

该解决方案源自 Stephan Mullers 解决方案。它也应该与动态填充的数据列表一起使用。

不幸的是,无法判断用户是单击数据列表中的项目还是通过按 Tab 键选择它还是手动键入了整个字符串。

于 2015-08-25T13:22:30.163 回答
17

由于缺乏可用于元素的事件,除了观看的事件(、等)<datalist>之外,无法从建议中进行选择。另请参阅我的答案:确定是否通过按 Enter 键从 HTML 5 数据列表中选择了一个元素inputchangeinput

要检查是否从列表中选择了选项,您应该将每个更改与可用选项进行比较。这意味着当用户手动输入精确值时,该事件也会触发,没有办法阻止它。

document.querySelector('input[list="items"]').addEventListener('input', onInput);

function onInput(e) {
   var input = e.target,
       val = input.value;
       list = input.getAttribute('list'),
       options = document.getElementById(list).childNodes;

  for(var i = 0; i < options.length; i++) {
    if(options[i].innerText === val) {
      // An item was selected from the list!
      // yourCallbackHere()
      alert('item selected: ' + val);
      break;
    }
  }
}
<input list="items" type="text" />
<datalist id="items">
  <option>item 1</option>
  <option>item 2</option>
</datalist>

于 2015-05-05T13:40:21.220 回答
12

利用keydown

与其他答案相反,可以检测是否键入或从列表中选择了选项。

键入和<datalist>单击都会触发输入的keydown侦听器,但只有键盘事件具有 key 属性。因此,如果 akeydown被触发且没有 key 属性,则您知道这是从列表中单击

演示:

const opts = document.getElementById('dlist').childNodes;
const dinput = document.getElementById('dinput');
let eventSource = null;
let value = '';

dinput.addEventListener('keydown', (e) => {
  eventSource = e.key ? 'input' : 'list';
});
dinput.addEventListener('input', (e) => {
  value = e.target.value;
  if (eventSource === 'list') {
    alert('CLICKED! ' + value);
  }
});
<input type="text" id="dinput" list="dlist" />

<datalist id="dlist">
  <option value="Value1">Text1</option>
  <option value="Value2">Text2</option>
</datalist>

请注意,如果单击的值已经在框中,它不会发出警报,但这可能是可取的。(这也可以通过使用将在keydown侦听器中切换的额外跟踪变量来添加。)

于 2020-11-30T12:26:09.370 回答
2

Datalist 不支持单击侦听器,并且 OnInput 非常昂贵,每次检查所有列表是否有任何变化。

我所做的是使用:

document.querySelector('#inputName').addEventListener("focusout", onInput);

每次客户端单击输入文本而不是单击其他任何位置时都会触发 FocusOut。如果他们点击文本,而不是点击其他地方,我假设他们输入了他们想要的值。

要检查该值是否有效,请执行与输入相同的操作:

   function onInput(e) {
        var val = document.querySelector('#inputName').value;
        options = document.getElementById('datalist').childNodes;
        for(var i = 0; i < options.length; i++) {
             if(options[i].innerText === val) {
                  console.log(val);
                  break;
             }
        }
    }
于 2018-03-03T18:07:16.320 回答
2

Shob 的答案是唯一可以检测选项何时被点击以及如果中间书面文本与选项匹配则不会触发的答案(例如:如果有人键入“Text1”以查看选项“Text11”、“Text12”等。即使“Text1”在数据列表中,它也不会触发)。

然而,原始答案似乎不适用于较新版本的 Firefox,因为该keydown事件不会在点击时触发,所以我对其进行了调整。

let keypress = false;
document.getElementById("dinput").addEventListener("keydown", (e) => {
    if(e.key) {
        keypress = true;
    }
});
document.getElementById("dinput").addEventListener('input', (e) => {
    let value = e.target.value;
    if (keypress === false) {
        // Clicked on option!
        console.debug("Value: " + value);
    }
    keypress = false;
});
<input type="text" id="dinput" list="dlist" />

<datalist id="dlist">
  <option value="Value1">Text1</option>
  <option value="Value2">Text2</option>
</datalist>

于 2021-02-24T13:29:48.860 回答
1
<input type="text" id="buscar" list="lalista"/>
<datalist id="lalista">
  <option value="valor1">texto1</option>
  <option value="valor2">texto2</option>
  <option value="valor3">texto3</option>  
</datalist>
//0 if event raised from datalist; 1 from keyboard
let idTimeFuekey = 0;  
buscar.oninput = function(){
    if(buscar.value && idTimeFuekey==0) {
        alert('Chévere! vino desde la lista')
    }
};
buscar.onkeydown = function(event){
    if(event.key){ //<-- for modern & non IE browser, more direct solution
        window.clearInterval(idTimeFuekey);
        idTimeFuekey = window.setInterval(function(){ //onkeydown --> idTimeFuekey++ (non 0)
            window.clearInterval(idTimeFuekey);
            idTimeFuekey = 0 //after 500ms onkeydown --> 0 (could work 500, 50, .. 1)
        }, 500) 
    }
}
于 2021-12-15T03:15:15.233 回答
0

好吧,至少在 Firefox 中,该onselect事件适用于输入标签

<input type="text" id="dinput" list="dlist" onselect="alert(this.value)"/>

<datalist id="dlist">
  <option value="Value1">Text1</option>
  <option value="Value2">Text2</option>
</datalist>

于 2021-07-13T01:49:03.980 回答