1(function() { 2 function focusSearchInput() { 3 // On the index page, we have a "#search" input. If we are on this page, we want to go back 4 // to this one and not the one in the header navbar. 5 const searchInput = document.getElementById("search"); 6 if (searchInput) { 7 searchInput.focus(); 8 } else { 9 document.getElementById("nav-search").focus(); 10 } 11 } 12 13 function focusFirstSearchResult() { 14 const elem = document.querySelector(".recent-releases-container a.release"); 15 if (elem) { 16 elem.focus(); 17 } 18 } 19 20 function getWrappingLi(elem) { 21 while (elem && elem.tagName !== "LI" && elem.tagName !== "BODY") { 22 elem = elem.parentElement; 23 } 24 if (elem.tagName === "BODY") { 25 return null; 26 } 27 return elem; 28 } 29 30 function focusOnLi(li) { 31 const elem = li.querySelector(".release"); 32 if (elem) { 33 elem.focus(); 34 } 35 } 36 37 function getKey(ev) { 38 if ("key" in ev && typeof ev.key !== "undefined") { 39 return ev.key; 40 } 41 return String.fromCharCode(ev.charCode || ev.keyCode); 42 } 43 44 function checkIfHasParent(elem, className) { 45 while (elem && elem.tagName !== "BODY") { 46 elem = elem.parentElement; 47 if (elem.classList.contains(className)) { 48 return true; 49 } 50 } 51 return false; 52 } 53 54 function handleKey(ev) { 55 if (ev.ctrlKey || ev.altKey || ev.metaKey) { 56 return; 57 } 58 if (ev.which === 27) { // Escape 59 document.activeElement.blur(); 60 return; 61 } 62 const tagName = document.activeElement.tagName; 63 // We want to check two things here: if an input or an element of the docs.rs topbar 64 // has the focus. If so, then we do nothing and simply return. 65 if (tagName === "INPUT" || 66 (tagName === "A" && 67 checkIfHasParent(document.activeElement, "nav-container"))) { 68 return; 69 } 70 71 if (ev.which === 40) { // Down arrow 72 ev.preventDefault(); 73 if (tagName === "BODY") { 74 focusFirstSearchResult(); 75 } else { 76 const wrappingLi = getWrappingLi(document.activeElement); 77 if (!wrappingLi) { 78 // Doesn't seem like we are in the crates list, let's focus the first element 79 // of the list then! 80 focusFirstSearchResult(); 81 } else if (wrappingLi.nextElementSibling) { 82 focusOnLi(wrappingLi.nextElementSibling); 83 } 84 } 85 } else if (ev.which === 38) { // Up arrow 86 ev.preventDefault(); 87 if (tagName === "A") { 88 const wrappingLi = getWrappingLi(document.activeElement); 89 if (!wrappingLi) { 90 // Doesn't seem like we are in the crates list, let's focus the first element 91 // of the list then! 92 focusFirstSearchResult(); 93 } else if (wrappingLi.previousElementSibling) { 94 focusOnLi(wrappingLi.previousElementSibling); 95 } else { 96 focusSearchInput(); 97 } 98 } else if (tagName === "BODY") { 99 focusFirstSearchResult(); 100 } 101 } else if (tagName !== "INPUT") { 102 switch (getKey(ev)) { 103 case "s": 104 case "S": 105 case "/": 106 ev.preventDefault(); 107 focusSearchInput(); 108 break; 109 } 110 } 111 } 112 113 function handleSortByChange() { 114 const inputSearch = document.getElementById("nav-search"); 115 const searchForm = document.getElementById("nav-search-form"); 116 if (inputSearch.value && searchForm) { 117 searchForm.submit(); 118 } 119 } 120 const searchSortBySel = document.getElementById("nav-sort"); 121 if (searchSortBySel) { 122 searchSortBySel.addEventListener("change", handleSortByChange); 123 } 124 125 document.onkeypress = handleKey; 126 document.onkeydown = handleKey; 127})();
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.