69 lines
2.2 KiB
JavaScript
69 lines
2.2 KiB
JavaScript
/**
|
|
* 종목 검색 자동완성 (Debounce 300ms)
|
|
*/
|
|
(function () {
|
|
const input = document.getElementById('searchInput');
|
|
const dropdown = document.getElementById('searchDropdown');
|
|
if (!input || !dropdown) return;
|
|
|
|
let debounceTimer = null;
|
|
|
|
input.addEventListener('input', () => {
|
|
clearTimeout(debounceTimer);
|
|
const q = input.value.trim();
|
|
|
|
if (q.length < 1) {
|
|
dropdown.classList.add('hidden');
|
|
return;
|
|
}
|
|
|
|
debounceTimer = setTimeout(() => fetchSuggestions(q), 300);
|
|
});
|
|
|
|
// 외부 클릭 시 드롭다운 닫기
|
|
document.addEventListener('click', (e) => {
|
|
if (!input.contains(e.target) && !dropdown.contains(e.target)) {
|
|
dropdown.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
// 엔터 시 검색 결과 페이지 이동
|
|
input.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter') {
|
|
const q = input.value.trim();
|
|
if (q) location.href = `/search?q=${encodeURIComponent(q)}`;
|
|
}
|
|
});
|
|
|
|
async function fetchSuggestions(q) {
|
|
try {
|
|
const resp = await fetch(`/api/search?q=${encodeURIComponent(q)}`);
|
|
if (!resp.ok) return;
|
|
const results = await resp.json();
|
|
renderDropdown(results);
|
|
} catch (e) {
|
|
console.error('검색 요청 실패:', e);
|
|
}
|
|
}
|
|
|
|
function renderDropdown(results) {
|
|
if (!results || results.length === 0) {
|
|
dropdown.classList.add('hidden');
|
|
return;
|
|
}
|
|
|
|
dropdown.innerHTML = results.slice(0, 8).map(item => `
|
|
<a href="/stock/${item.code}"
|
|
class="flex items-center justify-between px-4 py-2.5 hover:bg-gray-50 cursor-pointer border-b border-gray-50 last:border-0">
|
|
<div>
|
|
<span class="font-medium text-gray-800 text-sm">${item.name}</span>
|
|
<span class="text-xs text-gray-400 ml-2">${item.code}</span>
|
|
</div>
|
|
<span class="text-xs px-2 py-0.5 bg-gray-100 text-gray-500 rounded-full">${item.market}</span>
|
|
</a>
|
|
`).join('');
|
|
|
|
dropdown.classList.remove('hidden');
|
|
}
|
|
})();
|