@@ -48,9 +48,9 @@ function printTab(nb) {
4848 } ) ;
4949 onEachLazy ( document . getElementById ( "results" ) . childNodes , function ( elem ) {
5050 if ( nb === 0 ) {
51- elem . style . display = "" ;
51+ addClass ( elem , "active" ) ;
5252 } else {
53- elem . style . display = "none" ;
53+ removeClass ( elem , "active" ) ;
5454 }
5555 nb -= 1 ;
5656 } ) ;
@@ -875,106 +875,22 @@ window.initSearch = function(rawSearchIndex) {
875875 } ;
876876 }
877877
878- function initSearchNav ( ) {
879- var hoverTimeout ;
880-
881- var click_func = function ( e ) {
882- var el = e . target ;
883- // to retrieve the real "owner" of the event.
884- while ( el . tagName !== "TR" ) {
885- el = el . parentNode ;
886- }
887- var dst = e . target . getElementsByTagName ( "a" ) ;
888- if ( dst . length < 1 ) {
889- return ;
890- }
891- dst = dst [ 0 ] ;
892- if ( window . location . pathname === dst . pathname ) {
893- searchState . hideResults ( ) ;
894- document . location . href = dst . href ;
895- }
896- } ;
897- var mouseover_func = function ( e ) {
898- if ( searchState . mouseMovedAfterSearch ) {
899- var el = e . target ;
900- // to retrieve the real "owner" of the event.
901- while ( el . tagName !== "TR" ) {
902- el = el . parentNode ;
903- }
904- clearTimeout ( hoverTimeout ) ;
905- hoverTimeout = setTimeout ( function ( ) {
906- onEachLazy ( document . getElementsByClassName ( "search-results" ) , function ( e ) {
907- onEachLazy ( e . getElementsByClassName ( "result" ) , function ( i_e ) {
908- removeClass ( i_e , "highlighted" ) ;
909- } ) ;
910- } ) ;
911- addClass ( el , "highlighted" ) ;
912- } , 20 ) ;
913- }
914- } ;
915- onEachLazy ( document . getElementsByClassName ( "search-results" ) , function ( e ) {
916- onEachLazy ( e . getElementsByClassName ( "result" ) , function ( i_e ) {
917- i_e . onclick = click_func ;
918- i_e . onmouseover = mouseover_func ;
919- } ) ;
920- } ) ;
921-
922- searchState . input . onkeydown = function ( e ) {
923- // "actives" references the currently highlighted item in each search tab.
924- // Each array in "actives" represents a tab.
925- var actives = [ [ ] , [ ] , [ ] ] ;
926- // "current" is used to know which tab we're looking into.
927- var current = 0 ;
928- onEachLazy ( document . getElementById ( "results" ) . childNodes , function ( e ) {
929- onEachLazy ( e . getElementsByClassName ( "highlighted" ) , function ( h_e ) {
930- actives [ current ] . push ( h_e ) ;
931- } ) ;
932- current += 1 ;
933- } ) ;
934- var SHIFT = 16 ;
935- var CTRL = 17 ;
936- var ALT = 18 ;
878+ function nextTab ( direction ) {
879+ var next = ( searchState . currentTab + direction + 3 ) % searchState . focusedByTab . length ;
880+ searchState . focusedByTab [ searchState . currentTab ] = document . activeElement ;
881+ printTab ( next ) ;
882+ focusSearchResult ( ) ;
883+ }
937884
938- var currentTab = searchState . currentTab ;
939- if ( e . which === 38 ) { // up
940- if ( e . ctrlKey ) { // Going through result tabs.
941- printTab ( currentTab > 0 ? currentTab - 1 : 2 ) ;
942- } else {
943- if ( ! actives [ currentTab ] . length ||
944- ! actives [ currentTab ] [ 0 ] . previousElementSibling ) {
945- return ;
946- }
947- addClass ( actives [ currentTab ] [ 0 ] . previousElementSibling , "highlighted" ) ;
948- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
949- }
950- e . preventDefault ( ) ;
951- } else if ( e . which === 40 ) { // down
952- if ( e . ctrlKey ) { // Going through result tabs.
953- printTab ( currentTab > 1 ? 0 : currentTab + 1 ) ;
954- } else if ( ! actives [ currentTab ] . length ) {
955- var results = document . getElementById ( "results" ) . childNodes ;
956- if ( results . length > 0 ) {
957- var res = results [ currentTab ] . getElementsByClassName ( "result" ) ;
958- if ( res . length > 0 ) {
959- addClass ( res [ 0 ] , "highlighted" ) ;
960- }
961- }
962- } else if ( actives [ currentTab ] [ 0 ] . nextElementSibling ) {
963- addClass ( actives [ currentTab ] [ 0 ] . nextElementSibling , "highlighted" ) ;
964- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
965- }
966- e . preventDefault ( ) ;
967- } else if ( e . which === 13 ) { // return
968- if ( actives [ currentTab ] . length ) {
969- var elem = actives [ currentTab ] [ 0 ] . getElementsByTagName ( "a" ) [ 0 ] ;
970- document . location . href = elem . href ;
971- }
972- } else if ( [ SHIFT , CTRL , ALT ] . indexOf ( e . which ) !== - 1 ) {
973- // Does nothing, it's just to avoid losing "focus" on the highlighted element.
974- } else if ( actives [ currentTab ] . length > 0 ) {
975- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
976- }
977- } ;
885+ // focus the first search result on the active tab, or the result that
886+ // was focused last time this tab was active.
887+ function focusSearchResult ( ) {
888+ var target = searchState . focusedByTab [ searchState . currentTab ] ||
889+ document . querySelectorAll ( ".search-results.active a" ) . item ( 0 ) ||
890+ document . querySelectorAll ( "#titles > button" ) . item ( searchState . currentTab ) ;
891+ if ( target ) {
892+ target . focus ( ) ;
893+ }
978894 }
979895
980896 function buildHrefAndPath ( item ) {
@@ -1044,16 +960,16 @@ window.initSearch = function(rawSearchIndex) {
1044960 }
1045961
1046962 function addTab ( array , query , display ) {
1047- var extraStyle = "" ;
1048- if ( display === false ) {
1049- extraStyle = " style=\"display: none;\" " ;
963+ var extraClass = "" ;
964+ if ( display === true ) {
965+ extraClass = " active " ;
1050966 }
1051967
1052968 var output = "" ;
1053969 var duplicates = { } ;
1054970 var length = 0 ;
1055971 if ( array . length > 0 ) {
1056- output = "<table class=\"search-results\"" + extraStyle + ">" ;
972+ output = "<div class=\"search-results " + extraClass + "\ ">";
1057973
1058974 array . forEach ( function ( item ) {
1059975 var name , type ;
@@ -1069,20 +985,19 @@ window.initSearch = function(rawSearchIndex) {
1069985 }
1070986 length += 1 ;
1071987
1072- output += "<tr class=\"" + type + " result\"><td >" +
1073- "<a href =\"" + item . href + " \">" +
988+ output += "<a class=\"result- " + type + "\" href=\"" + item . href + "\" >" +
989+ "<div><div class =\"result-name \">" +
1074990 ( item . is_alias === true ?
1075991 ( "<span class=\"alias\"><b>" + item . alias + " </b></span><span " +
1076992 "class=\"grey\"><i> - see </i></span>" ) : "" ) +
1077993 item . displayPath + "<span class=\"" + type + "\">" +
1078- name + "</span></a></td><td>" +
1079- "<a href=\"" + item . href + "\">" +
994+ name + "</span></div><div>" +
1080995 "<span class=\"desc\">" + item . desc +
1081- " </span></a ></td ></tr >" ;
996+ " </span></div ></div ></a >" ;
1082997 } ) ;
1083- output += "</table >" ;
998+ output += "</div >" ;
1084999 } else {
1085- output = "<div class=\"search-failed\"" + extraStyle + ">No results :(<br/>" +
1000+ output = "<div class=\"search-failed\"" + extraClass + ">No results :(<br/>" +
10861001 "Try on <a href=\"https://duckduckgo.com/?q=" +
10871002 encodeURIComponent ( "rust " + query . query ) +
10881003 "\">DuckDuckGo</a>?<br/><br/>" +
@@ -1118,7 +1033,7 @@ window.initSearch = function(rawSearchIndex) {
11181033 {
11191034 var elem = document . createElement ( "a" ) ;
11201035 elem . href = results . others [ 0 ] . href ;
1121- elem . style . display = "none" ;
1036+ removeClass ( elem , "active" ) ;
11221037 // For firefox, we need the element to be in the DOM so it can be clicked.
11231038 document . body . appendChild ( elem ) ;
11241039 elem . click ( ) ;
@@ -1159,7 +1074,6 @@ window.initSearch = function(rawSearchIndex) {
11591074
11601075 search . innerHTML = output ;
11611076 searchState . showResults ( search ) ;
1162- initSearchNav ( ) ;
11631077 var elems = document . getElementById ( "titles" ) . childNodes ;
11641078 elems [ 0 ] . onclick = function ( ) { printTab ( 0 ) ; } ;
11651079 elems [ 1 ] . onclick = function ( ) { printTab ( 1 ) ; } ;
@@ -1437,6 +1351,50 @@ window.initSearch = function(rawSearchIndex) {
14371351 } ;
14381352 searchState . input . onpaste = searchState . input . onchange ;
14391353
1354+ searchState . outputElement ( ) . addEventListener ( "keydown" , function ( e ) {
1355+ // We only handle unmodified keystrokes here. We don't want to interfere with,
1356+ // for instance, alt-left and alt-right for history navigation.
1357+ if ( e . altKey || e . ctrlKey || e . shiftKey || e . metaKey ) {
1358+ return ;
1359+ }
1360+ // up and down arrow select next/previous search result, or the
1361+ // search box if we're already at the top.
1362+ if ( e . which === 38 ) { // up
1363+ var previous = document . activeElement . previousElementSibling ;
1364+ if ( previous ) {
1365+ console . log ( "previousElementSibling" , previous ) ;
1366+ previous . focus ( ) ;
1367+ } else {
1368+ searchState . focus ( ) ;
1369+ }
1370+ e . preventDefault ( ) ;
1371+ } else if ( e . which === 40 ) { // down
1372+ var next = document . activeElement . nextElementSibling ;
1373+ if ( next ) {
1374+ next . focus ( ) ;
1375+ }
1376+ var rect = document . activeElement . getBoundingClientRect ( ) ;
1377+ if ( window . innerHeight - rect . bottom < rect . height ) {
1378+ window . scrollBy ( 0 , rect . height ) ;
1379+ }
1380+ e . preventDefault ( ) ;
1381+ } else if ( e . which === 37 ) { // left
1382+ nextTab ( - 1 ) ;
1383+ e . preventDefault ( ) ;
1384+ } else if ( e . which === 39 ) { // right
1385+ nextTab ( 1 ) ;
1386+ e . preventDefault ( ) ;
1387+ }
1388+ } ) ;
1389+
1390+ searchState . input . addEventListener ( "keydown" , function ( e ) {
1391+ if ( e . which === 40 ) { // down
1392+ focusSearchResult ( ) ;
1393+ e . preventDefault ( ) ;
1394+ }
1395+ } ) ;
1396+
1397+
14401398 var selectCrate = document . getElementById ( "crate-search" ) ;
14411399 if ( selectCrate ) {
14421400 selectCrate . onchange = function ( ) {
0 commit comments