1function createTypeahead() { 2 return { 3 selectedIndex: -1, 4 init: function (elementName) { 5 this.input = document.getElementById(elementName); 6 if (!this.input) return; 7 this.resultHolder = document.getElementById(elementName + "Results"); 8 this.input.addEventListener("input", this.handleInput.bind(this)); 9 this.input.addEventListener("keydown", this.handleKeydown.bind(this)); 10 }, 11 handleInput: function () { 12 this.clearResults(); 13 const { value } = this.input; 14 if (value.length < 1) return; 15 const strongMatch = new RegExp("^" + value, "i"); 16 const weakMatch = new RegExp(value, "i"); 17 18 const results = resultList.filter(resultItem => weakMatch.test(resultItem.code)).sort((a, b) => { 19 if (strongMatch.test(a.code) && !strongMatch.test(b.code)) return -1; 20 if (!strongMatch.test(a.code) && strongMatch.test(b.code)) return 1; 21 return a.code < b.code ? -1 : 1; 22 }); 23 for (const resultItem of results) { 24 const item = document.createElement("div"); 25 const matchedText = weakMatch.exec(resultItem.code)[0]; 26 const template = ` 27 <a href="${resultItem.permalink}" class="subtitle-group subtitle-group-secondary"> 28 <div class="subtitle-group-text"> 29 <span>${resultItem.name}</span> 30 </div> 31 </a>`; 32 33 item.innerHTML = template; 34 item.dataset.permalink = resultItem.permalink; 35 this.resultHolder.appendChild(item); 36 item.addEventListener("click", this.handleClick); 37 } 38 }, 39 handleClick: function () { 40 window.location.href = this.dataset.permalink; 41 }, 42 getResults: function () { 43 return this.resultHolder.children; 44 }, 45 clearResults: function () { 46 this.selectedIndex = -1; 47 while (this.resultHolder.firstChild) { 48 this.resultHolder.removeChild(this.resultHolder.firstChild); 49 } 50 }, 51 handleKeydown: function (event) { 52 const { keyCode } = event; 53 const results = this.getResults(); 54 if (keyCode === 40 && this.selectedIndex < results.length - 1) { 55 this.selectedIndex++; 56 } else if (keyCode === 38 && this.selectedIndex >= 0) { 57 this.selectedIndex--; 58 } else if (keyCode === 13 && results[this.selectedIndex]) { 59 window.location.href = results[this.selectedIndex].dataset.permalink; 60 } 61 for (let i = 0; i < results.length; i++) { 62 const result = results[i]; 63 const selectedClass = "selected"; 64 if (i === this.selectedIndex) { 65 result.classList.add(selectedClass); 66 } else if (result.classList.contains(selectedClass)) { 67 result.classList.remove(selectedClass); 68 } 69 } 70 } 71 }; 72} 73 74// Create separate instances for desktop and mobile versions 75const desktopTypeahead = createTypeahead(); 76desktopTypeahead.init("searchTypeahead"); 77 78const mobileTypeahead = createTypeahead(); 79mobileTypeahead.init("searchTypeaheadMobile");
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.