@@ -809,3 +809,112 @@ function setupPreviewClarification($input, $previewDiv, previewInitial) {
809809$ ( function ( ) {
810810 $ ( '[data-toggle="tooltip"]' ) . tooltip ( ) ;
811811} ) ;
812+
813+ function initializeKeyboardShortcuts ( ) {
814+ var $body = $ ( 'body' ) ;
815+ var ignore = false ;
816+ $body . on ( 'keydown' , function ( e ) {
817+ // Check if the user is not typing in an input field.
818+ if ( e . target . tagName === 'INPUT' || e . target . tagName === 'TEXTAREA' ) {
819+ return ;
820+ }
821+ var key = e . key . toLowerCase ( ) ;
822+ if ( key === '?' ) {
823+ var $keyhelp = $ ( '#keyhelp' ) ;
824+ if ( $keyhelp . length ) {
825+ $keyhelp . toggleClass ( 'd-none' ) ;
826+ }
827+ return ;
828+ }
829+ if ( key === 'escape' ) {
830+ var $keyhelp = $ ( '#keyhelp' ) ;
831+ if ( $keyhelp . length && ! $keyhelp . hasClass ( 'd-none' ) ) {
832+ $keyhelp . addClass ( 'd-none' ) ;
833+ }
834+ }
835+
836+ if ( ! ignore && ! e . shiftKey && ( key === 'j' || key === 'k' ) ) {
837+ var parts = window . location . href . split ( '/' ) ;
838+ var lastPart = parts [ parts . length - 1 ] ;
839+ var params = lastPart . split ( '?' ) ;
840+ var currentNumber = parseInt ( params [ 0 ] ) ;
841+ if ( isNaN ( currentNumber ) ) {
842+ return ;
843+ }
844+ if ( key === 'j' ) {
845+ parts [ parts . length - 1 ] = currentNumber + 1 ;
846+ } else if ( key === 'k' ) {
847+ parts [ parts . length - 1 ] = currentNumber - 1 ;
848+ }
849+ if ( params . length > 1 ) {
850+ parts [ parts . length - 1 ] += '?' + params [ 1 ] ;
851+ }
852+ window . location = parts . join ( '/' ) ;
853+ } else if ( ! ignore && ( key === 's' || key === 't' || key === 'p' || key === 'j' || key === 'c' ) ) {
854+ if ( e . shiftKey && key === 's' ) {
855+ window . location = domjudge_base_url + '/jury/scoreboard' ;
856+ return ;
857+ }
858+ var type = key ;
859+ ignore = true ;
860+ var oldFunc = null ;
861+ var events = $ . _data ( $body [ 0 ] , 'events' ) ;
862+ if ( events && events . keydown ) {
863+ oldFunc = events . keydown [ 0 ] . handler ;
864+ }
865+ var sequence = '' ;
866+ var box = null ;
867+ var $sequenceBox = $ ( '<div class="keybox"></div>' ) ;
868+ box = $sequenceBox ;
869+ $sequenceBox . text ( type + sequence ) ;
870+ $sequenceBox . appendTo ( $body ) ;
871+ $body . on ( 'keydown' , function ( e ) {
872+ // Check if the user is not typing in an input field.
873+ if ( e . target . tagName === 'INPUT' || e . target . tagName === 'TEXTAREA' ) {
874+ ignore = false ;
875+ if ( box ) {
876+ box . remove ( ) ;
877+ }
878+ sequence = '' ;
879+ return ;
880+ }
881+ if ( e . key >= '0' && e . key <= '9' ) {
882+ sequence += e . key ;
883+ box . text ( type + sequence ) ;
884+ } else if ( e . key === 'Enter' ) {
885+ ignore = false ;
886+ switch ( type ) {
887+ case 's' :
888+ type = 'submissions' ;
889+ break ;
890+ case 't' :
891+ type = 'teams' ;
892+ break ;
893+ case 'p' :
894+ type = 'problems' ;
895+ break ;
896+ case 'c' :
897+ type = 'clarifications' ;
898+ break ;
899+ case 'j' :
900+ window . location = domjudge_base_url + '/jury/submissions/by-judging-id/' + sequence ;
901+ return ;
902+ }
903+ var redirect_to = domjudge_base_url + '/jury/' + type ;
904+ if ( sequence ) {
905+ redirect_to += '/' + sequence ;
906+ }
907+ window . location = redirect_to ;
908+ } else {
909+ ignore = false ;
910+ if ( box ) {
911+ box . remove ( ) ;
912+ }
913+ sequence = '' ;
914+ $body . off ( 'keydown' ) ;
915+ $body . on ( 'keydown' , oldFunc ) ;
916+ }
917+ } ) ;
918+ }
919+ } ) ;
920+ }
0 commit comments