()
| 1427 | } |
| 1428 | |
| 1429 | function wireCatalogSearch() { |
| 1430 | const input = document.getElementById("catalogSearch"); |
| 1431 | if (!input || input.dataset.searchReady === "1") return; |
| 1432 | input.dataset.searchReady = "1"; |
| 1433 | |
| 1434 | const suggest = document.getElementById("tagSuggest"); |
| 1435 | |
| 1436 | function hideSuggest() { |
| 1437 | if (suggest) suggest.innerHTML = ""; |
| 1438 | } |
| 1439 | |
| 1440 | function showTagSuggestions(prefix) { |
| 1441 | if (!suggest) return; |
| 1442 | suggest.innerHTML = ""; |
| 1443 | if (!prefix) { hideSuggest(); return; } |
| 1444 | const trashIds = new Set(folders.find((f) => f.id === TRASH_ID)?.items || []); |
| 1445 | const all = getAllTags(trashIds); |
| 1446 | const matches = all.filter(([t]) => t.toLowerCase().includes(prefix)); |
| 1447 | if (!matches.length) { hideSuggest(); return; } |
| 1448 | for (const [tag] of matches.slice(0, 8)) { |
| 1449 | const li = document.createElement("li"); |
| 1450 | li.className = "tag-suggest-item"; |
| 1451 | li.setAttribute("role", "option"); |
| 1452 | li.textContent = `#${tag}`; |
| 1453 | li.addEventListener("mousedown", (e) => { |
| 1454 | e.preventDefault(); |
| 1455 | input.value = `#${tag}`; |
| 1456 | catalogSearchQuery = `#${tag}`; |
| 1457 | hideSuggest(); |
| 1458 | render(); |
| 1459 | }); |
| 1460 | suggest.appendChild(li); |
| 1461 | } |
| 1462 | } |
| 1463 | |
| 1464 | input.addEventListener("input", () => { |
| 1465 | catalogSearchQuery = normalizeSearch(input.value); |
| 1466 | render(); |
| 1467 | const val = input.value; |
| 1468 | if (val.startsWith("#")) { |
| 1469 | showTagSuggestions(val.slice(1).toLowerCase()); |
| 1470 | } else { |
| 1471 | hideSuggest(); |
| 1472 | } |
| 1473 | }); |
| 1474 | |
| 1475 | input.addEventListener("blur", () => setTimeout(hideSuggest, 150)); |
| 1476 | input.addEventListener("keydown", (e) => { |
| 1477 | if (!suggest?.children.length) return; |
| 1478 | if (e.key === "Escape") { hideSuggest(); return; } |
| 1479 | const items = [...suggest.querySelectorAll(".tag-suggest-item")]; |
| 1480 | const active = suggest.querySelector(".tag-suggest-item.focused"); |
| 1481 | if (e.key === "ArrowDown") { |
| 1482 | e.preventDefault(); |
| 1483 | const next = active ? (items[items.indexOf(active) + 1] || items[0]) : items[0]; |
| 1484 | active?.classList.remove("focused"); |
| 1485 | next.classList.add("focused"); |
| 1486 | } else if (e.key === "ArrowUp") { |
no test coverage detected