Как лучше всего сделать раскрывающийся список с возможностью поиска, используя чистый JS? - PullRequest
0 голосов
/ 03 августа 2020

Вот мой html

            <div id = "country-input-wrapper" class = "selectInputWrapper">
                <input type="text" id = "country-input-text" class = "selectInputText"/>
                <div id = "country-selected-option-wrapper" class = "selectedOptionWrapper">
                    <div id = "country-option-1" value = "1" class = "selectOption">Armenia</div>
                    <div id = "country-option-2" value = "2" class = "selectOption">Brazil</div>
                    <div id = "country-option-3" value = "3" class = "selectOption">Chile</div>
                    <div id = "country-option-4" value = "4" class = "selectOption">Czech Republic</div>
                    <div id = "country-option-5" value = "5" class = "selectOption">Denmark</div>
                    <div id = "country-option-6" value = "6" class = "selectOption">France</div>
                    <div id = "country-option-7" value = "7" class = "selectOption">Egypt</div>
                    <div id = "country-option-8" value = "8" class = "selectOption">Ethiopia</div>
                    <div id = "country-option-9" value = "9" class = "selectOption">Germany</div>
                    <div id = "country-option-10" value = "10" class = "selectOption">Japan</div>
                    <div id = "country-option-11" value = "11" class = "selectOption">Monaco</div>
                    <div id = "country-option-12" value = "12" class = "selectOption">Nigeria</div>
                </div>
                <div id = "country-search-box" class = "inputSearchBox" contenteditable = "true"> </div>
            </div>
            <div id = "country-option-wrapper" class = "optionWrapper">
                <div id = "country-option-1" value = "1" class = "selectOption">Armenia</div>
                <div id = "country-option-2" value = "2" class = "selectOption">Brazil</div>
                <div id = "country-option-3" value = "3" class = "selectOption">Chile</div>
                <div id = "country-option-4" value = "4" class = "selectOption">Czech Republic</div>
                <div id = "country-option-5" value = "5" class = "selectOption">Denmark</div>
                <div id = "country-option-6" value = "6" class = "selectOption">France</div>
                <div id = "country-option-7" value = "7" class = "selectOption">Egypt</div>
                <div id = "country-option-8" value = "8" class = "selectOption">Ethiopia</div>
                <div id = "country-option-9" value = "9" class = "selectOption">Germany</div>
                <div id = "country-option-10" value = "10" class = "selectOption">Japan</div>
                <div id = "country-option-11" value = "11" class = "selectOption">Monaco</div>
                <div id = "country-option-12" value = "12" class = "selectOption">Nigeria</div>
            </div>
        </div>

Это CSS

        text-align: center;
    }
    .inputSearchBox{
        min-width: 100px;
        min-height: 30px;
        display: inline-block;
        margin: 2px;
        border: 1px solid #aaaaaa;
        border-radius: 3px;
    }
    .selectInputWrapper *{
        display: inline-block;
        text-align: left;
        max-width: 200px;
        width: 200px;
    }
    .selectToolWrapper{
        display: inline-block;
        border: solid 2px #aaaaaa;
        padding: 2px;
        margin: 3px;
        text-align: center;
        font-family: Cambria;
    }
    .selectedOptionWrapper{
        display: block;
    }
    .selectedOptionWrapper .selectOption{
        display: none;
        color: #ffffff;
        background-color: #70a0e0;
        padding: 2px 5px;
        border-radius: 3px;
        margin: 1px 0;
    }
    .selectedOptionWrapper .selected.selectOption{
        display: inline-block;
    }
    .optionWrapper{
        display: none;
        overflow-y: scroll;
        max-height: 100px;
    }
    .optionWrapper.selected{
        display: block;
    }
    .optionWrapper .selectOption{
        display: block;
        text-align: left;
        padding: 3px 5px;
        border-radius: 2px;
    }
    .optionWrapper .selectOption:hover{
        background-color: #3070d0b0;
        color: #ffffff;
    }
    .optionWrapper .hide.selectedOption{
        display: none;
    }
    .optionWrapper .selected.selectOption{
        display: none;
    }

Вот javascript

    function select(name){
        var inputBox = document.getElementById(name + "-input-text");
        var searchBox = document.getElementById(name + "-search-box");
        var optionWrapper = document.getElementById(name + "-option-wrapper");
        var options = optionWrapper.children;
        var selectedOptionWrapper = document.getElementById(name + "-selected-option-wrapper");
        var selectedOptions = selectedOptionWrapper.children;
        searchBox.addEventListener("click", function(){
            optionWrapper.classList.toggle("selected");
        });
        searchBox.addEventListener("input", function(){
            var searchCriterion = searchBox.innerText.toUpperCase();
            for (var i = 0 ; i < options.length ; i++){
                if(options[i].innerText.toUpperCase().search(searchCriterion) > -1){
                        options[i].classList.remove("hide");
                } else {
                    options[i].classList.add("hide");
                }
            }
        });
        for (var i = 0 ; i < options.length ; i++){
            options[i].addEventListener("click", function(){
                var currentValue = this.getAttribute("value");
                var valueList = inputBox.value.split(",");
                if(!(valueList.includes(currentValue))){
                    valueList.push(currentValue);
                    inputBox.value = valueList.join(",");
                    this.classList.toggle("selected");
                    selectedOptions[parseInt(currentValue)-1].classList.toggle("selected");
                }
            });
        }
        for (var i = 0 ; i < selectedOptions.length ; i++){
            selectedOptions[i].addEventListener("click", function(){
                var currentValue = this.getAttribute("value");
                var valueList = inputBox.value.split(",");
                if(valueList.includes(currentValue)){
                    valueList.splice(valueList.indexOf(currentValue), 1);
                    inputBox.value = valueList.join(",");
                    this.classList.toggle("selected");
                    options[parseInt(currentValue)-1].classList.toggle("selected");
                }
            });
        }
    }

Я не использовал appendchild, потому что это смещает окружающие элементы и затрудняет повторное возвращение невыбранных элементов на место (insertbefore создает исключение DOM, если окружающие узлы не существуют).

Есть предложения, чтобы сделать это более эффективным?

...