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

问题描述 投票:0回答:9

我正在使用

<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() {
javascript html dom-events html-datalist
9个回答
55
投票

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

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 键选择了它,还是手动输入了整个字符串。


21
投票

由于缺少

<datalist>
元素可用的事件,除了观看
input
的事件(
change
input
等)之外,没有办法从建议中进行选择。另请参阅我的回答:Determine if an element was selected from HTML 5 datalist by pressing enter key

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

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>


17
投票

使用
keydown

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

打字和

<datalist>
点击都会触发输入的
keydown
侦听器,但只有键盘事件具有键属性。因此,如果触发了没有键属性的
keydown
,您就知道这是来自列表的点击

演示:

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
侦听器中切换。)


4
投票

Datalist 实际上没有事件(并非所有浏览器),但您可以通过这种方式检测是否选择了 datalist 选项:

<input type="text" list="datalist" />

<datalist id="datalist">
  <option value="item 1" />
  <option value="item 2" />
</datalist>

window.addEventListener('input', function (e) {
 let event = e.inputType ? 'input' : 'option selected'
 console.log(event);
}, false);

演示


3
投票

Shob 的答案是唯一可以检测到选项何时被单击以及not 如果中间书面文本与选项匹配则触发的答案(例如:如果有人键入“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>


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

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

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>


0
投票

在遇到这个问题后没有找到合适的解决方案,我试了一下。

我所做的是在上面的事件切换变量之上查看给定输入事件的“inputType”,如下所示:

eventSource = false;

const selector = document.getElementById("yourElementID");

selector.addEventListener('input', function(evt) {
    if(!eventSource) {
        if(evt.inputType === "insertReplacementText") {
            console.log(selector.value);
        }
    }
});

selector.addEventListener('keydown', function(evt) {
    eventSource = !evt.key;
});

如果您希望允许用户搜索字段但仅在从数据列表本身选择时点击特定功能/事件,则此方法有效。希望对您有所帮助!

编辑:忘了说这是通过 Firefox 完成的,还没有在其他浏览器上测试过。

© www.soinside.com 2019 - 2024. All rights reserved.