@@ -51,9 +51,9 @@ function printTab(nb) {
5151 } ) ;
5252 onEachLazy ( document . getElementById ( "results" ) . childNodes , function ( elem ) {
5353 if ( nb === 0 ) {
54- elem . style . display = "" ;
54+ addClass ( elem , "active" ) ;
5555 } else {
56- elem . style . display = "none" ;
56+ removeClass ( elem , "active" ) ;
5757 }
5858 nb -= 1 ;
5959 } ) ;
@@ -878,106 +878,22 @@ window.initSearch = function(rawSearchIndex) {
878878 } ;
879879 }
880880
881- function initSearchNav ( ) {
882- var hoverTimeout ;
883-
884- var click_func = function ( e ) {
885- var el = e . target ;
886- // to retrieve the real "owner" of the event.
887- while ( el . tagName !== "TR" ) {
888- el = el . parentNode ;
889- }
890- var dst = e . target . getElementsByTagName ( "a" ) ;
891- if ( dst . length < 1 ) {
892- return ;
893- }
894- dst = dst [ 0 ] ;
895- if ( window . location . pathname === dst . pathname ) {
896- searchState . hideResults ( ) ;
897- document . location . href = dst . href ;
898- }
899- } ;
900- var mouseover_func = function ( e ) {
901- if ( searchState . mouseMovedAfterSearch ) {
902- var el = e . target ;
903- // to retrieve the real "owner" of the event.
904- while ( el . tagName !== "TR" ) {
905- el = el . parentNode ;
906- }
907- clearTimeout ( hoverTimeout ) ;
908- hoverTimeout = setTimeout ( function ( ) {
909- onEachLazy ( document . getElementsByClassName ( "search-results" ) , function ( e ) {
910- onEachLazy ( e . getElementsByClassName ( "result" ) , function ( i_e ) {
911- removeClass ( i_e , "highlighted" ) ;
912- } ) ;
913- } ) ;
914- addClass ( el , "highlighted" ) ;
915- } , 20 ) ;
916- }
917- } ;
918- onEachLazy ( document . getElementsByClassName ( "search-results" ) , function ( e ) {
919- onEachLazy ( e . getElementsByClassName ( "result" ) , function ( i_e ) {
920- i_e . onclick = click_func ;
921- i_e . onmouseover = mouseover_func ;
922- } ) ;
923- } ) ;
924-
925- searchState . input . onkeydown = function ( e ) {
926- // "actives" references the currently highlighted item in each search tab.
927- // Each array in "actives" represents a tab.
928- var actives = [ [ ] , [ ] , [ ] ] ;
929- // "current" is used to know which tab we're looking into.
930- var current = 0 ;
931- onEachLazy ( document . getElementById ( "results" ) . childNodes , function ( e ) {
932- onEachLazy ( e . getElementsByClassName ( "highlighted" ) , function ( h_e ) {
933- actives [ current ] . push ( h_e ) ;
934- } ) ;
935- current += 1 ;
936- } ) ;
937- var SHIFT = 16 ;
938- var CTRL = 17 ;
939- var ALT = 18 ;
881+ function nextTab ( direction ) {
882+ var next = ( searchState . currentTab + direction + 3 ) % searchState . focusedByTab . length ;
883+ searchState . focusedByTab [ searchState . currentTab ] = document . activeElement ;
884+ printTab ( next ) ;
885+ focusSearchResult ( ) ;
886+ }
940887
941- var currentTab = searchState . currentTab ;
942- if ( e . which === 38 ) { // up
943- if ( e . ctrlKey ) { // Going through result tabs.
944- printTab ( currentTab > 0 ? currentTab - 1 : 2 ) ;
945- } else {
946- if ( ! actives [ currentTab ] . length ||
947- ! actives [ currentTab ] [ 0 ] . previousElementSibling ) {
948- return ;
949- }
950- addClass ( actives [ currentTab ] [ 0 ] . previousElementSibling , "highlighted" ) ;
951- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
952- }
953- e . preventDefault ( ) ;
954- } else if ( e . which === 40 ) { // down
955- if ( e . ctrlKey ) { // Going through result tabs.
956- printTab ( currentTab > 1 ? 0 : currentTab + 1 ) ;
957- } else if ( ! actives [ currentTab ] . length ) {
958- var results = document . getElementById ( "results" ) . childNodes ;
959- if ( results . length > 0 ) {
960- var res = results [ currentTab ] . getElementsByClassName ( "result" ) ;
961- if ( res . length > 0 ) {
962- addClass ( res [ 0 ] , "highlighted" ) ;
963- }
964- }
965- } else if ( actives [ currentTab ] [ 0 ] . nextElementSibling ) {
966- addClass ( actives [ currentTab ] [ 0 ] . nextElementSibling , "highlighted" ) ;
967- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
968- }
969- e . preventDefault ( ) ;
970- } else if ( e . which === 13 ) { // return
971- if ( actives [ currentTab ] . length ) {
972- var elem = actives [ currentTab ] [ 0 ] . getElementsByTagName ( "a" ) [ 0 ] ;
973- document . location . href = elem . href ;
974- }
975- } else if ( [ SHIFT , CTRL , ALT ] . indexOf ( e . which ) !== - 1 ) {
976- // Does nothing, it's just to avoid losing "focus" on the highlighted element.
977- } else if ( actives [ currentTab ] . length > 0 ) {
978- removeClass ( actives [ currentTab ] [ 0 ] , "highlighted" ) ;
979- }
980- } ;
888+ // focus the first search result on the active tab, or the result that
889+ // was focused last time this tab was active.
890+ function focusSearchResult ( ) {
891+ var target = searchState . focusedByTab [ searchState . currentTab ] ||
892+ document . querySelectorAll ( ".search-results.active a" ) . item ( 0 ) ||
893+ document . querySelectorAll ( "#titles > button" ) . item ( searchState . currentTab ) ;
894+ if ( target ) {
895+ target . focus ( ) ;
896+ }
981897 }
982898
983899 function buildHrefAndPath ( item ) {
@@ -1047,16 +963,16 @@ window.initSearch = function(rawSearchIndex) {
1047963 }
1048964
1049965 function addTab ( array , query , display ) {
1050- var extraStyle = "" ;
1051- if ( display === false ) {
1052- extraStyle = " style=\"display: none;\" " ;
966+ var extraClass = "" ;
967+ if ( display === true ) {
968+ extraClass = " active " ;
1053969 }
1054970
1055971 var output = "" ;
1056972 var duplicates = { } ;
1057973 var length = 0 ;
1058974 if ( array . length > 0 ) {
1059- output = "<table class=\"search-results\"" + extraStyle + ">" ;
975+ output = "<div class=\"search-results " + extraClass + "\ ">";
1060976
1061977 array . forEach ( function ( item ) {
1062978 var name , type ;
@@ -1072,20 +988,19 @@ window.initSearch = function(rawSearchIndex) {
1072988 }
1073989 length += 1 ;
1074990
1075- output += "<tr class=\"" + type + " result\"><td >" +
1076- "<a href =\"" + item . href + " \">" +
991+ output += "<a class=\"result- " + type + "\" href=\"" + item . href + "\" >" +
992+ "<div><div class =\"result-name \">" +
1077993 ( item . is_alias === true ?
1078994 ( "<span class=\"alias\"><b>" + item . alias + " </b></span><span " +
1079995 "class=\"grey\"><i> - see </i></span>" ) : "" ) +
1080996 item . displayPath + "<span class=\"" + type + "\">" +
1081- name + "</span></a></td><td>" +
1082- "<a href=\"" + item . href + "\">" +
997+ name + "</span></div><div>" +
1083998 "<span class=\"desc\">" + item . desc +
1084- " </span></a ></td ></tr >" ;
999+ " </span></div ></div ></a >" ;
10851000 } ) ;
1086- output += "</table >" ;
1001+ output += "</div >" ;
10871002 } else {
1088- output = "<div class=\"search-failed\"" + extraStyle + ">No results :(<br/>" +
1003+ output = "<div class=\"search-failed\"" + extraClass + ">No results :(<br/>" +
10891004 "Try on <a href=\"https://duckduckgo.com/?q=" +
10901005 encodeURIComponent ( "rust " + query . query ) +
10911006 "\">DuckDuckGo</a>?<br/><br/>" +
@@ -1121,7 +1036,7 @@ window.initSearch = function(rawSearchIndex) {
11211036 {
11221037 var elem = document . createElement ( "a" ) ;
11231038 elem . href = results . others [ 0 ] . href ;
1124- elem . style . display = "none" ;
1039+ removeClass ( elem , "active" ) ;
11251040 // For firefox, we need the element to be in the DOM so it can be clicked.
11261041 document . body . appendChild ( elem ) ;
11271042 elem . click ( ) ;
@@ -1162,7 +1077,6 @@ window.initSearch = function(rawSearchIndex) {
11621077
11631078 search . innerHTML = output ;
11641079 searchState . showResults ( search ) ;
1165- initSearchNav ( ) ;
11661080 var elems = document . getElementById ( "titles" ) . childNodes ;
11671081 elems [ 0 ] . onclick = function ( ) { printTab ( 0 ) ; } ;
11681082 elems [ 1 ] . onclick = function ( ) { printTab ( 1 ) ; } ;
@@ -1440,6 +1354,50 @@ window.initSearch = function(rawSearchIndex) {
14401354 } ;
14411355 searchState . input . onpaste = searchState . input . onchange ;
14421356
1357+ searchState . outputElement ( ) . addEventListener ( "keydown" , function ( e ) {
1358+ // We only handle unmodified keystrokes here. We don't want to interfere with,
1359+ // for instance, alt-left and alt-right for history navigation.
1360+ if ( e . altKey || e . ctrlKey || e . shiftKey || e . metaKey ) {
1361+ return ;
1362+ }
1363+ // up and down arrow select next/previous search result, or the
1364+ // search box if we're already at the top.
1365+ if ( e . which === 38 ) { // up
1366+ var previous = document . activeElement . previousElementSibling ;
1367+ if ( previous ) {
1368+ console . log ( "previousElementSibling" , previous ) ;
1369+ previous . focus ( ) ;
1370+ } else {
1371+ searchState . focus ( ) ;
1372+ }
1373+ e . preventDefault ( ) ;
1374+ } else if ( e . which === 40 ) { // down
1375+ var next = document . activeElement . nextElementSibling ;
1376+ if ( next ) {
1377+ next . focus ( ) ;
1378+ }
1379+ var rect = document . activeElement . getBoundingClientRect ( ) ;
1380+ if ( window . innerHeight - rect . bottom < rect . height ) {
1381+ window . scrollBy ( 0 , rect . height ) ;
1382+ }
1383+ e . preventDefault ( ) ;
1384+ } else if ( e . which === 37 ) { // left
1385+ nextTab ( - 1 ) ;
1386+ e . preventDefault ( ) ;
1387+ } else if ( e . which === 39 ) { // right
1388+ nextTab ( 1 ) ;
1389+ e . preventDefault ( ) ;
1390+ }
1391+ } ) ;
1392+
1393+ searchState . input . addEventListener ( "keydown" , function ( e ) {
1394+ if ( e . which === 40 ) { // down
1395+ focusSearchResult ( ) ;
1396+ e . preventDefault ( ) ;
1397+ }
1398+ } ) ;
1399+
1400+
14431401 var selectCrate = document . getElementById ( "crate-search" ) ;
14441402 if ( selectCrate ) {
14451403 selectCrate . onchange = function ( ) {
0 commit comments