
本文将指导你如何实现一个具备智能搜索提示和输入验证的 Autocomplete 组件。该组件能够在用户输入时提供实时搜索建议,支持在字符串任意位置匹配,并限制用户输入,仅允许选择预设选项,从而增强用户体验和数据准确性。
1. 初始状态显示全部选项
原代码只有在用户输入至少一个字符后才会显示匹配的选项。为了在光标置于空字段时显示所有选项,我们需要修改 input 事件监听器中的逻辑。
inp.addEventListener("input", function(e) { var a, b, i, val = this.value; closeAllLists(); // 修改此处:如果输入为空,则显示所有选项 if (!val) { // 显示所有选项的逻辑 a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i < arr.length; i++) { b = document.createElement("DIV"); b.innerHTML = arr[i]; b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } return false; } currentFocus = -1; a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i < arr.length; i++) { if (arr[i].substr(0, val.length).toUpperCase() == val.toUpperCase()) { b = document.createElement("DIV"); b.innerHTML = "" + arr[i].substr(0, val.length) + ""; b.innerHTML += arr[i].substr(val.length); b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } } });
这段代码在 input 事件监听器中添加了一个条件判断。如果输入框的值为空,则创建一个包含所有选项的列表并显示出来。
2. 实现任意位置匹配
原代码只匹配字符串的开头,要实现任意位置匹配,需要修改 if 条件判断。
inp.addEventListener("input", function(e) { var a, b, i, val = this.value; closeAllLists(); if (!val) { a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i < arr.length; i++) { b = document.createElement("DIV"); b.innerHTML = arr[i]; b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } return false; } currentFocus = -1; a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i -1) { b = document.createElement("DIV"); // 高亮匹配部分 (可选) let index = arr[i].toUpperCase().indexOf(val.toUpperCase()); let pre = arr[i].substring(0, index); let match = arr[i].substring(index, index + val.length); let post = arr[i].substring(index + val.length); b.innerHTML = pre + "" + match + "" + post; b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } } });
这里使用了 indexOf 方法来检查字符串中是否包含指定的子字符串。如果 indexOf 返回的值大于 -1,则表示找到了匹配项。 同时,为了更好的用户体验,可以对匹配到的字符进行高亮显示。
3. 限制输入,只允许选择 Autocomplete 值
为了限制用户只能输入 Autocomplete 列表中存在的值,我们需要添加验证逻辑。
// 在 autocomplete 函数外部保存原始数组var originalArray = [...arr];inp.addEventListener("blur", function(e) { // 验证输入是否在原始数组中 if (originalArray.indexOf(inp.value) === -1 && inp.value !== "") { inp.value = ""; // 清空输入框 // 或者显示错误提示 alert("Please select a valid fruit from the list."); }});
这段代码监听了输入框的 blur 事件(失去焦点时触发)。当输入框失去焦点时,它会检查输入的值是否在原始数组中。如果不在,则清空输入框的值,并可选择显示错误提示。 同时,在初始化 autocomplete 函数时,需要将原始数组复制一份保存下来,避免后续修改。
4. 完整代码示例
* { box-sizing: border-box;}body { background-color: #f1f1f1;}#regForm { background-color: #ffffff; margin: 10px auto; font-family: Raleway; padding: 10px; width: 90%; min-width: 300px;}h1 { text-align: center;}input { padding: 10px; width: 100%; font-size: 17px; font-family: Raleway; border: 1px solid #aaaaaa;}input.invalid { background-color: #ffdddd;}.tab { display: none;}button { background-color: #04AA6D; color: #ffffff; border: none; padding: 10px 20px; font-size: 17px; font-family: Raleway; cursor: pointer;}button:hover { opacity: 0.8;}#prevBtn { background-color: #bbbbbb;}.step { height: 15px; width: 15px; margin: 0 2px; background-color: #bbbbbb; border: none; border-radius: 50%; display: inline-block; opacity: 0.5;}.step.active { opacity: 1;}.step.finish { background-color: #04AA6D;}.autocomplete { position: relative; display: inline-block;}.autocomplete-items { position: absolute; border: 1px solid #d4d4d4; border-bottom: none; border-top: none; z-index: 99; /*position the autocomplete items to be the same width as the container:*/ 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 { /*when hovering an item:*/ background-color: #e9e9e9;}.autocomplete-active { /*when navigating through the items using the arrow keys:*/ background-color: DodgerBlue !important; color: #fff;} Your Nutrition Needs:
Your Fruit:
function autocomplete(inp, arr) { var currentFocus; var originalArray = [...arr]; inp.addEventListener("input", function(e) { var a, b, i, val = this.value; closeAllLists(); if (!val) { a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i < arr.length; i++) { b = document.createElement("DIV"); b.innerHTML = arr[i]; b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } return false; } currentFocus = -1; a = document.createElement("DIV"); a.setAttribute("id", this.id + "autocomplete-list"); a.setAttribute("class", "autocomplete-items"); this.parentNode.appendChild(a); for (i = 0; i -1) { b = document.createElement("DIV"); let index = arr[i].toUpperCase().indexOf(val.toUpperCase()); let pre = arr[i].substring(0, index); let match = arr[i].substring(index, index + val.length); let post = arr[i].substring(index + val.length); b.innerHTML = pre + "" + match + "" + post; b.innerHTML += ""; b.addEventListener("click", function(e) { inp.value = this.getElementsByTagName("input")[0].value; closeAllLists(); }); a.appendChild(b); } } }); inp.addEventListener("keydown", function(e) { var x = document.getElementById(this.id + "autocomplete-list"); if (x) x = x.getElementsByTagName("div"); if (e.keyCode == 40) { currentFocus++; addActive(x); } else if (e.keyCode == 38) { currentFocus--; addActive(x); } else if (e.keyCode == 13) { e.preventDefault(); if (currentFocus > -1) { if (x) x[currentFocus].click(); } } }); inp.addEventListener("blur", function(e) { if (originalArray.indexOf(inp.value) === -1 && inp.value !== "") { inp.value = ""; alert("Please select a valid fruit from the list."); } }); function addActive(x) { if (!x) return false; removeActive(x); if (currentFocus >= x.length) currentFocus = 0; if (currentFocus < 0) currentFocus = (x.length - 1); x[currentFocus].classList.add("autocomplete-active"); } function removeActive(x) { for (var i = 0; i < x.length; i++) { x[i].classList.remove("autocomplete-active"); } } function closeAllLists(elmnt) { var x = document.getElementsByClassName("autocomplete-items"); for (var i = 0; i < x.length; i++) { if (elmnt != x[i] && elmnt != inp) { x[i].parentNode.removeChild(x[i]); } } } document.addEventListener("click", function(e) { closeAllLists(e.target); });}var fruitlist = [ "Apple", "Mango", "Pear", "Banana", "Berry"];autocomplete(document.getElementById("myFruitList"), fruitlist);
5. 注意事项
性能优化: 对于大型数据集,建议使用更高效的搜索算法,例如使用 Trie 树或对数据进行预处理。用户体验: 可以添加加载动画、错误提示等,进一步提升用户体验。安全性: 如果 Autocomplete 的数据来自后端,请确保对输入进行适当的验证和转义,防止 XSS 攻击。
6. 总结
通过本文的教程,你已经学会了如何实现一个具备智能搜索提示和输入验证的 Autocomplete 组件。这个组件可以极大地提升用户体验,并确保输入数据的准确性。你可以根据实际需求,对代码进行进一步的定制和优化。
以上就是实现智能搜索提示和输入验证的 Autocomplete 组件教程的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1324195.html
微信扫一扫
支付宝扫一扫