如何传递此和 addEventListener 以从列表中拾取项目并将其设置在输入字段上
2021-08-19
455
我正在开发一个自动完成功能,并填充一个列表,目前列表只显示结果,但我无法选择它们以将其添加到输入元素。 以下是代码示例:
var search_terms = ['a', 'b', 'c'];
function autocompleteMatch(input) {
if (input == '') {
return [];
}
var reg = new RegExp(input);
return search_terms.filter(function(term) {
if (term.match(reg)) {
return term;
}
});
}
function showResults(val) {
res = document.getElementById("result");
res.innerHTML = '';
let list = '';
let terms = autocompleteMatch(val);
for (i = 0; i < terms.length; i++) {
list += '<li>' + terms[i] + '</li>';
}
res.innerHTML = '<ul>' + list + '</ul>';
}
<input type="text" class="form-control" placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)" name="post" required id="id_post" onKeyUp="showResults(this.value)">
<span class="fas fa-asterisk" style="font-size:12px;color:red;position:absolute; right:20px;top:12px;" id="asterix"></span>
<div id="result"></div>
任何建议将列表中的元素添加到输入。我搜索了类似的建议,但我无法将答案应用到我的代码中。
编辑:在我的情况下,这里发布的解决方案不起作用,因为脚本的调用
<script type="text/javascript" src="app.js" charset="utf-8"></script>
在顶部。因此它失败了,出现 Uncaught TypeError:无法读取 null 的属性“addEventListener”。将
<script>
部分移动到
<body>
末尾后,建议的答案开始起作用。
3个回答
这是应该的工作方式吗?我向
res
添加了事件监听器,用于测试是否单击了
<li>
。如果是,则将
<li>
的 innerHTML 作为值插入到
<input>
中。使用
dispatchEvent()
,我更新列表,就像它是一个 keyup 事件一样。
var search_terms = ['abc', 'abcde', 'abde'];
var res = document.getElementById("result");
var id_post = document.getElementById("id_post");
function autocompleteMatch(input) {
if (input == '') {
return [];
}
var reg = new RegExp(input)
return search_terms.filter(function(term) {
if (term.match(reg)) {
return term;
}
});
}
function showResults(val) {
let terms = autocompleteMatch(val);
list = terms.map(term => `<li>${term}</li>`).join('');
res.innerHTML = '<ul>' + list + '</ul>';
}
res.addEventListener('click', e => {
if(e.target.nodeName == "LI"){
id_post.value = e.target.innerHTML;
id_post.dispatchEvent(new Event('keyup'));
}
});
<input type="text" class="form-control" placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)" name="post" required id="id_post" onKeyUp="showResults(this.value)">
<div id="result"></div>
chrwahl
2021-08-19
考虑到您的原始代码,缺少一些细节,例如 自动完成 功能和键盘事件(向上/向下/输入)。
1) HTML
// form (autocomplete off) disables autocomplete integration with external tools like 1password
<form autocomplete="off">
<div class="autocomplete" id="autocomplete-container">
<input id="autocomplete-input" type="text" placeholder="Type Something...">
</div>
<input type="submit">
</form>
2) 可能选项列表 ( 要使其动态,请在将其绑定到自动完成方法之前加载列表 )
const data = ["Aaa", "Aab", "Aac", "Abc", "Bbc", "Bbd", "Xpto", "Item1", "Item2", "SomethingElse"];
3) 自动完成功能
const autocomplete = (container, inputElement, list) => {
var currentFocus = -1;
inputElement.addEventListener('input', () => {
var autocompleteText = inputElement.value;
hideList();
if (!autocompleteText) {
return false;
}
const autocompleteList = document.createElement('div');
autocompleteList.setAttribute('id', 'autocomplete-list');
autocompleteList.setAttribute('class', 'autocomplete-items');
container.appendChild(autocompleteList);
list.forEach((item, index) => {
if (
item.substr(0, autocompleteText.length).toUpperCase() ===
autocompleteText.toUpperCase()
) {
const tempId = `hiddenInput_${index}`;
const text = item.substr(0, autocompleteText.length);
const autocompleteMatch = document.createElement('div');
autocompleteMatch.innerHTML = `<strong>${text}</strong>`;
autocompleteMatch.innerHTML += item.substr(autocompleteText.length);
autocompleteMatch.innerHTML += `<input type='hidden' id='${tempId}' value='${item}'>`;
autocompleteMatch.addEventListener('click', (event) => {
const clickedElement = event.target.getElementsByTagName('input')[0];
inputElement.value = clickedElement.value;
hideList();
});
autocompleteList.appendChild(autocompleteMatch);
}
});
});
inputElement.addEventListener('keydown', function (e) {
const autoCompleteList = document.getElementById('autocomplete-list');
var autoCompleteDiv;
if (autoCompleteList) {
autoCompleteDiv = autoCompleteList.getElementsByTagName('div');
}
if (e.keyCode === 40) {
// KEY DOWN
currentFocus++;
addActive(autoCompleteDiv);
} else if (e.keyCode === 38) {
// KEY UP
currentFocus--;
addActive(autoCompleteDiv);
} else if (e.keyCode === 13) {
// ENTER
e.preventDefault();
if (currentFocus > -1 && autoCompleteDiv) {
autoCompleteDiv[currentFocus].click();
}
}
});
const addActive = (item) => {
if (!item) {
return false;
}
removeActive(item);
if (currentFocus >= item.length) {
currentFocus = 0;
}
if (currentFocus < 0) {
currentFocus = item.length - 1;
}
item[currentFocus].classList.add('autocomplete-active');
};
const removeActive = (autoCompleteItems) => {
Array.from(autoCompleteItems).forEach((item) => {
item.classList.remove('autocomplete-active');
});
};
const hideList = (element) => {
var autoCompleteItems =
document.getElementsByClassName('autocomplete-items');
if (autoCompleteItems && autoCompleteItems.length > 0) {
Array.from(autoCompleteItems).forEach((item) => {
if (element !== item && element !== inputElement) {
item.parentNode.removeChild(item);
}
});
}
};
document.addEventListener('click', (event) => hideList(event.target));
};
// this part binds the autocomplete with the HTML
window.addEventListener('load', function () {
const container = document.getElementById('autocomplete-container');
const inputElement = document.getElementById('autocomplete-input');
autocomplete(container, inputElement, data);
});
- CSS
* { box-sizing: border-box; }
body {
font: 16px Arial;
}
.autocomplete {
display: inline-block;
position: relative;
width: 300px;
}
input {
border: 1px solid transparent;
background-color: #f1f1f1;
padding: 10px;
font-size: 16px;
}
input[type=text] {
background-color: #f1f1f1;
width: 100%;
}
input[type=submit] {
background-color: DodgerBlue;
color: #fff;
}
.autocomplete-items {
position: absolute;
border: 1px solid #d4d4d4;
border-bottom: none;
border-top: none;
z-index: 99;
top: 100%;
left: 0;
right: 0;
}
.autocomplete-items div {
padding: 10px;
cursor: pointer;
background-color: #fff;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: DodgerBlue !important;
color: #ffffff;
}
基于 W3School - 操作方法 - 自动完成
实时版本 - Codesandbox
Daniel Santana
2021-08-19
尝试此代码
var searchTerms = ["OneDrive sync issue", "Abcde", "123456"];
var result = document.getElementById("result");
rul = document.createElement("ul");
result.appendChild(rul);
rul.classList.add("datalist");
for(var x = 0; x < searchTerms.length; x++ ){
rli = document.createElement("li");
rul.appendChild(rli);
rli.innerHTML = searchTerms[x];
rli.classList.add("d-none");
rli.addEventListener("click", function(){
document.getElementById("id_post").value = this.innerHTML;
this.classList.add("d-none");
});
}
function showResults(v){
var ListItems = rul.querySelectorAll("li");
for(var i = 0; i < ListItems.length; i++){
var c = ListItems[i].innerHTML.toLowerCase();
v = v.toLowerCase();
if(c.indexOf(v) > -1 && v !== ""){
ListItems[i].classList.remove("d-none");
}
else{
ListItems[i].classList.add("d-none");
}
}
}
.d-none{ display:none; }
.datalist li{ cursor:pointer; }
<input
type="text"
class="form-control"
placeholder="Explain in fewer words with the primary product key word (Eg: OneDrive sync issue, etc.)"
name="post"
required
id="id_post"
onKeyUp="showResults(this.value)">
<span
class="fas fa-asterisk"
style="font-size:12px;color:red;position:absolute; right:20px;top:12px;"
id="asterix"></span>
<div id="result"></div>
nxt
2021-08-19