Files
stocksearch/static/js/search.js
2026-03-31 19:32:59 +09:00

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');
}
})();