[UI λ§λ€κΈ°][Vanilla JS] μλμμ± κ²μμ°½ ꡬννκΈ°
μν°λ ν리μ¨λ³΄λ© FE μ±λ¦°μ§ μ¬μ λ―Έμ μΌλ‘ μλμμ± κ²μμ°½μ ꡬνν΄ λ³΄μμ΅λλ€. μ΄λ₯Ό μν΄, νμ μ¬μ©νλ μλΉμ€λ€μ κ²μ κΈ°λ₯μ μ μ¬ν κ΄μ°°νλ©΄μ, μλμμ±μ΄ μΌλ§λ κ²μ κ²½νμ ν₯μμν€λμ§ μμΌ κΉ¨λ«κ² λμμ΅λλ€.
μλμμ± κ²μμ°½μ μ£Όμ κΈ°λ₯λ€μ λ€μκ³Ό κ°μ΄ ꡬνν΄λ³΄μμ΅λλ€.
import dummy from "./data.js";
const searchInput = document.querySelector(".search-input");
const suggestionContainer = document.querySelector(".suggestionContainer");
let selectedIndex = -1;
let prevSelectedIndex = -1;
// κ²μμ°½μ μ
λ ₯μ μ μ λͺ©λ‘μ νν°λ§
searchInput.addEventListener("input", function () {
const inputValue = this.value.toLowerCase();
const filteredSuggestions = dummy.filter(
(suggestion) =>
suggestion.description.toLowerCase().includes(inputValue) || suggestion.key.toLowerCase().includes(inputValue)
);
renderSuggestions(filteredSuggestions);
});
// μ μ λͺ©λ‘μ λ λλ§
function renderSuggestions(filteredSuggestions) {
if (filteredSuggestions.length === 0) {
suggestionContainer.classList.remove("show");
return;
}
suggestionContainer.innerHTML = "";
let currentType = null;
for (const suggestion of filteredSuggestions) {
if (currentType !== suggestion.type) {
const typeLi = document.createElement("li");
typeLi.innerHTML = suggestion.type;
typeLi.classList.add("suggestion-type");
suggestionContainer.appendChild(typeLi);
currentType = suggestion.type;
}
const li = document.createElement("li");
li.innerHTML = `${suggestion.description}`;
li.classList.add("suggestion-item");
li.addEventListener("click", () => {
searchInput.value = li.innerHTML;
suggestionContainer.classList.remove("show");
});
suggestionContainer.appendChild(li);
}
suggestionContainer.classList.add("show");
selectedIndex = -1;
}
// νμ΄ν ν€λ₯Ό μ¬μ©νμ¬ μ μ λͺ©λ‘μ νμνκ³ Enter ν€λ₯Ό μ¬μ©νμ¬ μ ν
searchInput.addEventListener("keydown", function (e) {
const items = suggestionContainer.querySelectorAll(":scope > .suggestion-item");
if (e.key === "ArrowDown") {
selectedIndex = selectedIndex < items.length - 1 ? selectedIndex + 1 : 0;
updateSelection();
} else if (e.key === "ArrowUp") {
selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : items.length - 1;
updateSelection();
} else if (e.key === "Enter" && selectedIndex > -1) {
searchInput.value = items[selectedIndex].innerHTML;
suggestionContainer.classList.remove("show");
selectedIndex = -1;
prevSelectedIndex = -1;
}
});
function updateSelection() {
const items = suggestionContainer.querySelectorAll(":scope > .suggestion-item");
if (prevSelectedIndex === selectedIndex || selectedIndex === -1) return;
// μ΄μ μ μ νλ νλͺ©μ ν΄λμ€ μ κ±°
if (prevSelectedIndex !== -1) {
items[prevSelectedIndex].classList.remove("selected");
}
// μλ‘ μ νλ νλͺ©μ ν΄λμ€ μΆκ°
items[selectedIndex].classList.add("selected");
items[selectedIndex].scrollIntoView({ behavior: "smooth", block: "nearest" });
prevSelectedIndex = selectedIndex;
}
// κ²μμ°½ μΈλΆ ν΄λ¦μ μΆμ² λͺ©λ‘ μ¨κΈ°κΈ°
document.addEventListener("click", function (e) {
if (!searchInput.contains(e.target) && !suggestionContainer.contains(e.target)) {
suggestionContainer.classList.remove("show");
}
});
ν¬κ² μ΄ 4κ°μ§μ κΈ°λ₯μΌλ‘ ꡬμ±λμ΄ μμ΅λλ€:
1. κ²μ μ λ ₯ μ²λ¦¬
- μ¬μ©μκ° μ λ ₯ νλμ νμ΄νν λλ§λ€ μ΄λ²€νΈκ° λ°μν©λλ€.
- dummy λ°°μ΄μ κ° νλͺ©μ λν΄ filter ν¨μλ₯Ό μ¬μ©νμ¬ (λμλ¬Έμ κ΅¬λΆ μμ΄) κ²μ¬ν©λλ€.
- νν°λ§λ κ²°κ³Όλ₯Ό renderSuggestions ν¨μμ μ λ¬νμ¬ νλ©΄μ νμν©λλ€.
2. μ μ λͺ©λ‘ λ λλ§
νν°λ§λ μ μ λͺ©λ‘μ νλ©΄μ νμνκ³ , μ μ νλͺ©λ€μ νμ λ³λ‘ κ·Έλ£Ήννμ¬ νμν©λλ€.
- νν°λ§λ μ μμ μννλ©΄μ:
- μλ‘μ΄ νμ μ μ μμ΄ λνλλ©΄ νμ ν€λλ₯Ό μμ±ν©λλ€.
- κ° μ μμ λν΄ λ¦¬μ€νΈ μμ΄ν μ μμ±ν©λλ€.
- κ° μμ΄ν μ ν΄λ¦ μ΄λ²€νΈ 리μ€λλ₯Ό μΆκ°νμ¬, ν΄λ¦ μ ν΄λΉ μ μμ μ λ ₯ νλμ μ±μ°κ³ μ μ λͺ©λ‘μ μ¨κΉλλ€.
3. ν€λ³΄λ λ€λΉκ²μ΄μ
μ λ ₯ νλμ μ λ ₯λ ν€μ λ°λΌ λ€λ₯Έ κΈ°λ₯μ μνν©λλ€.
- μ/μλ νμ΄ν ν€λ‘ μ μ λͺ©λ‘μ νμν μ μκ² ν©λλ€.
- Enter ν€λ‘ μ νν μ μμ μ λ ₯μ°½μ μ μ©ν©λλ€.
- μ νλ νλͺ©μ μκ°μ μΌλ‘ νμνκ³ μ€ν¬λ‘€ν©λλ€.
4. μΈλΆ ν΄λ¦ μ²λ¦¬
κ²μμ°½μ΄λ μ μ λͺ©λ‘ μΈλΆλ₯Ό ν΄λ¦νλ©΄ μ μ λͺ©λ‘μ μ¨κΉλλ€.
See the Pen Auto-complete search box by κ³½μ€μ² [νμ](μννΈμ¨μ΄μ΅ν©λν μ»΄ν¨ν°κ³΅νλΆ) (@tkuffnrk-the-typescripter) on CodePen.
μ¬μ©μμ μ λ ₯μ μ¦κ°μ μΌλ‘ λ°μνλ μΈν°νμ΄μ€λ₯Ό λ§λ€λ©΄μ μ±λ₯ μ΅μ νμ μ€μμ±μ 체κ°νμ΅λλ€. μμΌλ‘λ λλ°μ΄μ±μ΄λ μ°λ‘νλ§ κΈ°λ²μ μ μ©νμ¬ λμ± ν¨μ¨μ μΈ κ²μ κΈ°λ₯μ ꡬνν΄λ³΄κ³ μ ν©λλ€.