You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jQuery Auto populate Dropdown问题求助:匹配逻辑与输入残留修复

国家名称自动补全下拉框功能修复

问题描述

我正在实现一个带国家名称的自动补全下拉框功能,需求如下:

  • 用户在contenteditable类型的div中输入字符时,下拉框显示与输入字符匹配的选项
  • 点击下拉框选项后,该选项以带删除按钮的标签形式添加到输入区域,同时从下拉框中移除
  • 删除标签时,该选项需重新回到下拉框

目前遇到两个问题:

  1. 下拉框未根据输入字符筛选匹配选项,仅在聚焦时显示
  2. 选中选项添加为标签后,输入的字符未从contenteditable div中清除

修复后的完整代码

HTML

<div class="multi-eids">
  <div class="input" contenteditable="true" id="countryInput"></div>
  <div class="multi-eids-dropdown" id="countryDropdown"></div>
</div>

CSS

.dropdown {
    display: none;
    border: 1px solid #ccc;
    max-height: 100px;
    overflow-y: auto;
}
.input {
  border:solid 1px #ddd;
  min-height: 48px;
  padding: 8px;
}

span .remove {
    display: inline-block;
    margin-left: 5px;
    cursor: pointer;
}

.multi-eids {position: relative;}
.multi-eids-dropdown { 
  position: absolute;
  overflow-y: auto;
  top: 60px; 
  left: 0; 
  width: 100%;
  max-height: 197px; 
  min-height: 60px; 
  border: solid 1px #ddd;
  background: #fff;
  box-shadow: 0 0 5px #ddd;
  display: none; /* 默认隐藏下拉框 */
}
.eid-item { 
  display: flex; 
  padding: 8px; 
  border-bottom: solid 1px #ddd;
  cursor: pointer;
}
.eid-item:hover {      
  background: #f5f5f5;   
}
.eid-item:last-child {border-bottom: none;}
.selected-item {
  display: inline-flex;
  padding: 4px 8px;
  font-size: 12px;
  background: #f5f5f5;
  border: solid 1px #ddd;
  border-radius: 4px;
  height: 24px;
  margin: 0 4px 4px 0;
  justify-content: space-between;
  align-items: center;
}
.selected-item .close {
  margin: 0 0 0 4px; 
  font-weight: 600; 
  cursor: pointer;
}

JavaScript

$(document).ready(function() {
    const countries = ["USA", "Canada", "UK", "Australia", "France", "Germany", "Japan"];
    
    const $input = $("#countryInput");
    const $dropdown = $("#countryDropdown");
    
    // 获取当前输入的纯文本(过滤已选中的标签内容)
    function getUserInput() {
        let inputText = "";
        // 遍历输入区域的子节点,只取文本节点内容
        $input.contents().each(function() {
            if (this.nodeType === Node.TEXT_NODE) {
                inputText += this.textContent.trim();
            }
        });
        return inputText.toLowerCase();
    }
    
    // 填充并筛选下拉框
    function populateDropdown() {
        $dropdown.empty();
        const inputVal = getUserInput();
        
        countries.forEach(function(country) {
            // 检查国家是否已被选中,以及是否匹配输入内容
            const isSelected = $input.find(`.selected-item:contains(${country})`).length > 0;
            const isMatch = inputVal === "" || country.toLowerCase().includes(inputVal);
            
            if (!isSelected && isMatch) {
                const $item = $("<div class='eid-item'>").text(country);
                $item.on("click", function() {
                    addCountryToInput(country);
                    $item.remove();
                    $dropdown.hide();
                });
                $dropdown.append($item);
            }
        });
        
        // 如果没有匹配项,隐藏下拉框
        $dropdown.toggle($dropdown.children().length > 0);
    }

    function addCountryToInput(country) {
        const $span = $("<span contenteditable='false' class='selected-item'>").text(country);
        const $remove = $("<span class='close'>x</span>");
        
        $remove.on("click", function() {
            $span.remove();
            populateDropdown(); // 删除后重新渲染下拉框
        });
        
        $span.append($remove);
        $input.append($span);
        
        // 清除输入的字符,并添加空白文本节点保证光标可输入
        $input.contents().each(function() {
            if (this.nodeType === Node.TEXT_NODE) {
                $(this).remove();
            }
        });
        $input.append(document.createTextNode(""));
        
        // 将光标定位到末尾
        const range = document.createRange();
        const sel = window.getSelection();
        range.selectNodeContents($input.get(0));
        range.collapse(false);
        sel.removeAllRanges();
        sel.addRange(range);
    }

    // 输入时触发筛选
    $input.on("input", function() {
        populateDropdown();
    });

    // 聚焦时显示下拉框(如果有未选中项)
    $input.on("focus", function() {
        populateDropdown();
    });

    // 点击外部隐藏下拉框
    $(document).on("click", function(event) {
        if (!$input.is(event.target) && !$dropdown.is(event.target) && $dropdown.has(event.target).length === 0) {
            $dropdown.hide();
        }
    });
});

修复关键点说明

  1. 下拉筛选逻辑修复

    • 新增getUserInput函数,专门提取输入区域的纯文本内容(排除已添加的标签)
    • 在populateDropdown中添加匹配逻辑:只有未被选中且名称包含输入字符(不区分大小写)的国家才会显示
    • 输入为空时,显示所有未被选中的国家
  2. 输入字符清除修复

    • 在addCountryToInput中,遍历输入区域的文本节点并删除,清除用户输入的字符
    • 添加空白文本节点,确保用户可以继续输入
    • 处理光标定位,保证添加标签后光标自动移到输入区域末尾

内容的提问来源于stack exchange,提问作者PRANAV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:52:05