jQuery Auto populate Dropdown问题求助:匹配逻辑与输入残留修复
国家名称自动补全下拉框功能修复
问题描述
我正在实现一个带国家名称的自动补全下拉框功能,需求如下:
- 用户在contenteditable类型的div中输入字符时,下拉框显示与输入字符匹配的选项
- 点击下拉框选项后,该选项以带删除按钮的标签形式添加到输入区域,同时从下拉框中移除
- 删除标签时,该选项需重新回到下拉框
目前遇到两个问题:
- 下拉框未根据输入字符筛选匹配选项,仅在聚焦时显示
- 选中选项添加为标签后,输入的字符未从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(); } }); });
修复关键点说明
下拉筛选逻辑修复
- 新增
getUserInput函数,专门提取输入区域的纯文本内容(排除已添加的标签) - 在
populateDropdown中添加匹配逻辑:只有未被选中且名称包含输入字符(不区分大小写)的国家才会显示 - 输入为空时,显示所有未被选中的国家
- 新增
输入字符清除修复
- 在
addCountryToInput中,遍历输入区域的文本节点并删除,清除用户输入的字符 - 添加空白文本节点,确保用户可以继续输入
- 处理光标定位,保证添加标签后光标自动移到输入区域末尾
- 在
内容的提问来源于stack exchange,提问作者PRANAV
相关产品推荐
相关产品推荐

