在纯 JavaScript 中实现 AutoComplete 下拉菜单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28842355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:38:24  来源:igfitidea点击:

Implementing a AutoComplete dropdown in plain JavaScript

javascript

提问by Raj

Here is my HTML

这是我的 HTML

<h2>Please Enter the Value in the Box(click on the desired value)</h2>
<input id='value' type="text" autocomplete="on" placeholder="country" />
<div id="dropdown">
    <select name="list" id="list"></select>
</div>

Here is my JavaScript

这是我的 JavaScript

var arr = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua &amp; Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia &amp; Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Cape Verde","Cayman Islands","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica","Cote D Ivtheitroade","Croatia","Cruise Ship","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kuwait","Kyrgyz Republic","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Mauritania","Mauritius","Mexico","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Namibia","Nepal","Netherlands","Netherlands Antilles","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Norway","Oman","Pakistan","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre &amp; Miquelon","Samoa","San Marino","Satellite","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","South Korea","Spain","Sri Lanka","St Kitts &amp; Nevis","St Lucia","St Vincent","St. Lucia","Sudan","Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad &amp; Tobago","Tunisia","Turkey","Turkmenistan","Turks &amp; Caicos","Uganda","Ukraine","United Arab Emirates","United Kingdom","Uruguay","Uzbekistan","Venezuela","Vietnam","Virgin Islands (US)","Yemen","Zambia","Zimbabwe"];
var input = document.getElementById('value');
var optionsVal = document.getElementById('list');

input.addEventListener('keyup', show);
optionsVal.onclick = function(){
    setVal(this);
};

//shows the list
function show(){
    var dropdown = document.getElementById('dropdown');
    dropdown.style.display = 'none';

    optionsVal.options.length = 0;

    if(input.value){
        dropdown.style.display = 'block';
        optionsVal.size = 3;
        var textCountry = input.value;

        for(var i = 0; i < arr.length; i++){
            if(arr[i].indexOf(textCountry) !== -1){
                //addvalue
                addValue(arr[i],arr[i]);

            }
        }

    }
}

function addValue(text,val){
    var createOptions = document.createElement('option');
    optionsVal.appendChild(createOptions);
    createOptions.text = text;
    createOptions.value = val;
}

//Settin the value in the box by firing the click event
function setVal(selectedVal){
    input.value = selectedVal.value;
    document.getElementById('dropdown').style.display='none';
}

This issue i am running into is the logic involved when checking for the input value and showing the values in the dropdown. For example if i type in 'u' only countries 'Anguilla, Antigua' show up instead of any country with 'u' in it. I know the issue lies where i am checking for indexOf, but i am stuck here.

我遇到的这个问题是检查输入值并在下拉列表中显示值时所涉及的逻辑。例如,如果我输入“u”,则只会出现“安圭拉、安提瓜”国家,而不是任何包含“u”的国家。我知道问题出在我检查 indexOf 的地方,但我被困在这里。

Also how can i keep the dropdown size dynamic to the values found? Your feedback would be great in improving the overall problem too

另外,如何使下拉大小与找到的值保持一致?您的反馈对改善整体问题也很有帮助

采纳答案by Mouser

Why not use a matchinstead of indexOf?
Added benefit this will search case insensitive. http://jsfiddle.net/e6220t92/2/. Fiddle also has an attempt to increase the size of the select box.

为什么不使用 amatch代替indexOf
增加的好处是搜索不区分大小写。http://jsfiddle.net/e6220t92/2/。Fiddle 也有增加选择框大小的尝试。

    //CODE
    var testableRegExp = new RegExp(RegExp.escape(textCountry),"i");
    if (arr[i].match(testableRegExp ) )
    {
       //logic
    }
    //CODE

//Use this function to replace potential characters that could break the regex
RegExp.escape= function(s) {
    return s.replace(/[-\/\^$*+?.()|[\]{}]/g, '\$&');
};

回答by Mouser

The problem is that you need to resize the option list after filtering the input elements.

问题是您需要在过滤输入元素后调整选项列表的大小。

You can do this by removing the line:

您可以通过删除该行来做到这一点:

optionsVal.size = 3;

And changing the for loop that filters options to add a resize that is the same size as the filtered results:

并更改过滤选项的 for 循环以添加与过滤结果相同大小的调整大小:

for(var i = 0; i < arr.length; i++){
    if(arr[i].indexOf(textCountry) !== -1){
        //addvalue
        addValue(arr[i],arr[i]);
        optionsVal.size = optionsVal.options.length;
    }
}

It's a little ugly if there are no options, and really long when you enter something like just like an "a", but I think this is what you are after.

如果没有选项,这有点难看,而且当你输入像“a”这样的东西时真的很长,但我认为这就是你所追求的。

Changed show() function:

更改 show() 函数:

//shows the list
function show(){
    var dropdown = document.getElementById('dropdown');
    dropdown.style.display = 'none';

optionsVal.options.length = 0;

if(input.value){
    dropdown.style.display = 'block';
    var textCountry = input.value;

    for(var i = 0; i < arr.length; i++){
        if(arr[i].indexOf(textCountry) !== -1){
            //addvalue
            addValue(arr[i],arr[i]);
            optionsVal.size = optionsVal.options.length;
        }
    }

    }
}