单击 HTML5 数据列表选项时执行操作

IT技术 javascript html dom-events html-datalist
2021-03-11 15:50:23

我正在使用 <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 花”项,如果我单击它,我需要执行一个事件。

我怎样才能做到这一点?

option.addEventListener("click", function() {
option.addEventListener("onclick", function() {
option.addEventListener("change", function() {
6个回答

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

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 键或手动键入整个字符串来选择它。

过滤器在 IE 中不起作用,我们有其他解决方案吗?
2021-04-21 15:50:23
你还必须区分这和一个paste事件......非常不同的路径可能不会结束到相同的终点
2021-04-23 15:50:23
在 IE11 上,这与在 Firefox 中完全一样。您使用的是什么版本的 IE,哪些功能不起作用?
2021-05-06 15:50:23

由于缺少可用于<datalist>元素的事件,因此除了观看input的事件(、 等)之外change无法从建议中进行选择input也可以在这里查看我的答案:确定是否通过按 Enter 键从 HTML 5 数据列表中选择了一个元素

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

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>

感谢您的狙击手,但是这不适用于我的解决方案,我认为是因为数据列表正在不断重新填充和清空。
2021-05-01 15:50:23
完美运行,如果您使用 <option value="item 1"> 设置了选项,那么您需要使用 options[i].value 而不是 innerText
2021-05-03 15:50:23

利用 keydown

相反,其他的答案,它可以检测一个选项是否被输入或从列表中选择。

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

演示:

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侦听器中切换的额外跟踪变量来添加。)

很好的解决方案。不幸的是Safari浏览器(版本15.1)不会触发keydown选择时,事件optiondatalist,所以eventSource不会得到更新,并保持在最后的状态。
2021-04-19 15:50:23
优秀的!这是非常聪明的。我试图将鼠标和键事件都连接到输入上,但很奇怪的是,尽管单击了下拉列表中的选项,但它却引发了键事件。这似乎是区分黑白两者的唯一方法。
2021-04-26 15:50:23

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

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>