diff --git a/network-poc/static/index.html b/network-poc/static/index.html index a5e74c7..e8ba4c8 100644 --- a/network-poc/static/index.html +++ b/network-poc/static/index.html @@ -1105,10 +1105,11 @@
-
+
$ - +
@@ -1982,13 +1983,105 @@ return false; } + // Dropdown-autocompletionin tila + const dropdown = document.getElementById('term-dropdown'); + let dropdownItems = []; + let dropdownIdx = -1; + let dropdownPrefix = ''; // Inputin alku joka säilyy valinnan yhteydessä + + function getCandidates(val) { + const words = val.trimEnd().split(/\s+/); + for (let depth = words.length; depth >= 1; depth--) { + const prefix = words.slice(0, depth).join(' '); + const partial = words[depth] || ''; + // Esimerkkipromptit + if (kpnExamples[prefix] && !partial) { + return { items: kpnExamples[prefix], prefix: prefix + ' ' }; + } + // Komennot + const candidates = kpnCommands[prefix]; + if (candidates) { + const matches = partial ? candidates.filter(c => c.startsWith(partial)) : candidates; + if (matches.length > 0) { + return { items: matches, prefix: prefix + ' ' }; + } + } + } + if (!val.trim()) return { items: kpnCommands['kpn'] || [], prefix: 'kpn ' }; + return { items: [], prefix: val }; + } + + function showDropdown(items, prefix) { + if (!dropdown || items.length === 0) { hideDropdown(); return; } + dropdownItems = items; + dropdownPrefix = prefix; + dropdownIdx = -1; + dropdown.innerHTML = items.map((item, i) => + `
${esc(item)}
` + ).join(''); + dropdown.style.display = 'block'; + + // Klikkaus-handlerit + dropdown.querySelectorAll('.term-dd-item').forEach(el => { + el.addEventListener('mouseenter', () => highlightDropdown(parseInt(el.dataset.idx))); + el.addEventListener('click', () => { selectDropdown(); termInput.focus(); }); + }); + } + + function hideDropdown() { + if (dropdown) { dropdown.style.display = 'none'; dropdown.innerHTML = ''; } + dropdownItems = []; + dropdownIdx = -1; + } + + function highlightDropdown(idx) { + dropdownIdx = idx; + dropdown.querySelectorAll('.term-dd-item').forEach((el, i) => { + el.style.background = i === idx ? '#30363d' : 'transparent'; + el.style.color = i === idx ? '#58a6ff' : '#c9d1d9'; + }); + // Varmistetaan näkyvyys + const active = dropdown.children[idx]; + if (active) active.scrollIntoView({ block: 'nearest' }); + } + + function selectDropdown() { + if (dropdownIdx >= 0 && dropdownIdx < dropdownItems.length) { + termInput.value = dropdownPrefix + dropdownItems[dropdownIdx] + (dropdownItems[dropdownIdx].startsWith('"') ? '' : ' '); + } + hideDropdown(); + } + termInput?.addEventListener('keydown', (e) => { + // Dropdown auki: nuolet navigoi, Enter/Tab valitsee, Esc sulkee + if (dropdown && dropdown.style.display === 'block') { + if (e.key === 'ArrowDown') { + e.preventDefault(); + highlightDropdown(Math.min(dropdownIdx + 1, dropdownItems.length - 1)); + return; + } + if (e.key === 'ArrowUp') { + e.preventDefault(); + highlightDropdown(Math.max(dropdownIdx - 1, 0)); + return; + } + if ((e.key === 'Enter' || e.key === 'Tab') && dropdownIdx >= 0) { + e.preventDefault(); + selectDropdown(); + return; + } + if (e.key === 'Escape') { + e.preventDefault(); + hideDropdown(); + return; + } + } + if (e.key === 'Tab' && e.shiftKey) { - // Shift-TAB: poista viimeinen sana (tai lainausmerkkien sisältö) e.preventDefault(); + hideDropdown(); const val = termInput.value.trimEnd(); if (!val) return; - // Jos päättyy lainausmerkkeihin, poista koko lainattu osa const quoteMatch = val.match(/^(.+\s)".*"?$|^(.+\s)'.*'?$/); if (quoteMatch) { termInput.value = (quoteMatch[1] || quoteMatch[2]).trimEnd() + ' '; @@ -1998,18 +2091,26 @@ } } else if (e.key === 'Tab') { e.preventDefault(); - tabComplete(termInput); + // Näytä dropdown tai täydennä jos vain yksi vaihtoehto + const { items, prefix } = getCandidates(termInput.value); + if (items.length === 1) { + termInput.value = prefix + items[0] + (items[0].startsWith('"') ? '' : ' '); + hideDropdown(); + } else if (items.length > 1) { + showDropdown(items, prefix); + } } else if (e.key === 'Enter') { + hideDropdown(); const cmd = termInput.value.trim(); if (cmd) termExec(cmd); termInput.value = ''; - } else if (e.key === 'ArrowUp') { + } else if (e.key === 'ArrowUp' && !dropdown?.style.display?.includes('block')) { e.preventDefault(); if (termHistIdx < termHistory.length - 1) { termHistIdx++; termInput.value = termHistory[termHistIdx]; } - } else if (e.key === 'ArrowDown') { + } else if (e.key === 'ArrowDown' && !dropdown?.style.display?.includes('block')) { e.preventDefault(); if (termHistIdx > 0) { termHistIdx--; @@ -2021,6 +2122,11 @@ } }); + // Suljetaan dropdown kun klikataan muualle + document.addEventListener('click', (e) => { + if (!termInput?.contains(e.target) && !dropdown?.contains(e.target)) hideDropdown(); + }); + // Klikkaa terminaalipaneelia → fokusoi input termPanel?.addEventListener('click', () => termInput?.focus());