44// Local js definitions:
55/* global addClass, getCurrentValue, hasClass */
66/* global onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
7+ /* global hideThemeButtonState, showThemeButtonState */
78
89if ( ! String . prototype . startsWith ) {
910 String . prototype . startsWith = function ( searchString , position ) {
@@ -47,6 +48,14 @@ function getSearchElement() {
4748 return document . getElementById ( "search" ) ;
4849}
4950
51+ function getThemesElement ( ) {
52+ return document . getElementById ( "theme-choices" ) ;
53+ }
54+
55+ function getThemePickerElement ( ) {
56+ return document . getElementById ( "theme-picker" ) ;
57+ }
58+
5059// Sets the focus on the search bar at the top of the page
5160function focusSearchBar ( ) {
5261 getSearchInput ( ) . focus ( ) ;
@@ -137,10 +146,6 @@ function defocusSearchBar() {
137146 sidebar . appendChild ( div ) ;
138147 }
139148 }
140- var themePickers = document . getElementsByClassName ( "theme-picker" ) ;
141- if ( themePickers && themePickers . length > 0 ) {
142- themePickers [ 0 ] . style . display = "none" ;
143- }
144149 }
145150
146151 function hideSidebar ( ) {
@@ -155,10 +160,6 @@ function defocusSearchBar() {
155160 filler . remove ( ) ;
156161 }
157162 document . getElementsByTagName ( "body" ) [ 0 ] . style . marginTop = "" ;
158- var themePickers = document . getElementsByClassName ( "theme-picker" ) ;
159- if ( themePickers && themePickers . length > 0 ) {
160- themePickers [ 0 ] . style . display = null ;
161- }
162163 }
163164
164165 function showSearchResults ( search ) {
@@ -376,6 +377,7 @@ function defocusSearchBar() {
376377 document . title = titleBeforeSearch ;
377378 }
378379 defocusSearchBar ( ) ;
380+ hideThemeButtonState ( ) ;
379381 }
380382
381383 function handleShortcut ( ev ) {
@@ -412,7 +414,57 @@ function defocusSearchBar() {
412414 case "?" :
413415 displayHelp ( true , ev ) ;
414416 break ;
417+
418+ default :
419+ var themePicker = getThemePickerElement ( ) ;
420+ if ( themePicker . parentNode . contains ( ev . target ) ) {
421+ handleThemeKeyDown ( ev ) ;
422+ }
423+ }
424+ }
425+ }
426+
427+ function handleThemeKeyDown ( ev ) {
428+ var active = document . activeElement ;
429+ var themes = getThemesElement ( ) ;
430+ switch ( getVirtualKey ( ev ) ) {
431+ case "ArrowUp" :
432+ ev . preventDefault ( ) ;
433+ if ( active . previousElementSibling && ev . target . id !== "theme-picker" ) {
434+ active . previousElementSibling . focus ( ) ;
435+ } else {
436+ showThemeButtonState ( ) ;
437+ themes . lastElementChild . focus ( ) ;
438+ }
439+ break ;
440+ case "ArrowDown" :
441+ ev . preventDefault ( ) ;
442+ if ( active . nextElementSibling && ev . target . id !== "theme-picker" ) {
443+ active . nextElementSibling . focus ( ) ;
444+ } else {
445+ showThemeButtonState ( ) ;
446+ themes . firstElementChild . focus ( ) ;
447+ }
448+ break ;
449+ case "Enter" :
450+ case "Return" :
451+ case "Space" :
452+ if ( ev . target . id === "theme-picker" && themes . style . display === "none" ) {
453+ ev . preventDefault ( ) ;
454+ showThemeButtonState ( ) ;
455+ themes . firstElementChild . focus ( ) ;
415456 }
457+ break ;
458+ case "Home" :
459+ ev . preventDefault ( ) ;
460+ themes . firstElementChild . focus ( ) ;
461+ break ;
462+ case "End" :
463+ ev . preventDefault ( ) ;
464+ themes . lastElementChild . focus ( ) ;
465+ break ;
466+ // The escape key is handled in handleEscape, not here,
467+ // so that pressing escape will close the menu even if it isn't focused
416468 }
417469 }
418470
0 commit comments