@@ -13,6 +13,24 @@ export class KeyboardNavigation {
1313 /** The workspace. */
1414 protected workspace : Blockly . WorkspaceSvg ;
1515
16+ /** Event handler run when the workspace gains focus. */
17+ private focusListener : ( ) => void ;
18+
19+ /** Event handler run when the workspace loses focus. */
20+ private blurListener : ( ) => void ;
21+
22+ /** Keyboard navigation controller instance for the workspace. */
23+ private navigationController : NavigationController ;
24+
25+ /**
26+ * These fields are used to preserve the workspace's initial state to restore
27+ * it when/if keyboard navigation is disabled.
28+ */
29+ private injectionDivTabIndex : string | null ;
30+ private workspaceParentTabIndex : string | null ;
31+ private originalTheme : Blockly . Theme ;
32+ private originalCursor : Blockly . Cursor | null ;
33+
1634 /**
1735 * Constructs the keyboard navigation.
1836 *
@@ -22,33 +40,80 @@ export class KeyboardNavigation {
2240 constructor ( workspace : Blockly . WorkspaceSvg ) {
2341 this . workspace = workspace ;
2442
25- const navigationController = new NavigationController ( ) ;
26- navigationController . init ( ) ;
27- navigationController . addWorkspace ( workspace ) ;
28- navigationController . enable ( workspace ) ;
29- navigationController . listShortcuts ( ) ;
43+ this . navigationController = new NavigationController ( ) ;
44+ this . navigationController . init ( ) ;
45+ this . navigationController . addWorkspace ( workspace ) ;
46+ this . navigationController . enable ( workspace ) ;
47+ this . navigationController . listShortcuts ( ) ;
3048
49+ this . originalTheme = workspace . getTheme ( ) ;
3150 this . setGlowTheme ( ) ;
51+ this . originalCursor = workspace . getMarkerManager ( ) . getCursor ( ) ;
3252 installCursor ( workspace . getMarkerManager ( ) ) ;
3353
3454 // Ensure that only the root SVG G (group) has a tab index.
55+ this . injectionDivTabIndex = workspace
56+ . getInjectionDiv ( )
57+ . getAttribute ( 'tabindex' ) ;
3558 workspace . getInjectionDiv ( ) . removeAttribute ( 'tabindex' ) ;
59+ this . workspaceParentTabIndex = workspace
60+ . getParentSvg ( )
61+ . getAttribute ( 'tabindex' ) ;
3662 workspace . getParentSvg ( ) . removeAttribute ( 'tabindex' ) ;
3763
38- workspace . getSvgGroup ( ) . addEventListener ( 'focus' , ( ) => {
39- navigationController . setHasFocus ( workspace , true ) ;
40- } ) ;
41- workspace . getSvgGroup ( ) . addEventListener ( 'blur' , ( ) => {
42- navigationController . setHasFocus ( workspace , false ) ;
43- } ) ;
64+ this . focusListener = ( ) => {
65+ this . navigationController . setHasFocus ( workspace , true ) ;
66+ } ;
67+ this . blurListener = ( ) => {
68+ this . navigationController . setHasFocus ( workspace , false ) ;
69+ } ;
70+
71+ workspace . getSvgGroup ( ) . addEventListener ( 'focus' , this . focusListener ) ;
72+ workspace . getSvgGroup ( ) . addEventListener ( 'blur' , this . blurListener ) ;
4473 // Temporary workaround for #136.
4574 // TODO(#136): fix in core.
46- workspace . getParentSvg ( ) . addEventListener ( 'focus' , ( ) => {
47- navigationController . setHasFocus ( workspace , true ) ;
48- } ) ;
49- workspace . getParentSvg ( ) . addEventListener ( 'blur' , ( ) => {
50- navigationController . setHasFocus ( workspace , false ) ;
51- } ) ;
75+ workspace . getParentSvg ( ) . addEventListener ( 'focus' , this . focusListener ) ;
76+ workspace . getParentSvg ( ) . addEventListener ( 'blur' , this . blurListener ) ;
77+ }
78+
79+ /**
80+ * Disables keyboard navigation for this navigator's workspace.
81+ */
82+ dispose ( ) {
83+ // Temporary workaround for #136.
84+ // TODO(#136): fix in core.
85+ this . workspace
86+ . getParentSvg ( )
87+ . removeEventListener ( 'blur' , this . blurListener ) ;
88+ this . workspace
89+ . getParentSvg ( )
90+ . removeEventListener ( 'focus' , this . focusListener ) ;
91+
92+ this . workspace . getSvgGroup ( ) . removeEventListener ( 'blur' , this . blurListener ) ;
93+ this . workspace
94+ . getSvgGroup ( )
95+ . removeEventListener ( 'focus' , this . focusListener ) ;
96+
97+ if ( this . workspaceParentTabIndex ) {
98+ this . workspace
99+ . getParentSvg ( )
100+ . setAttribute ( 'tabindex' , this . workspaceParentTabIndex ) ;
101+ }
102+
103+ if ( this . injectionDivTabIndex ) {
104+ this . workspace
105+ . getInjectionDiv ( )
106+ . setAttribute ( 'tabindex' , this . injectionDivTabIndex ) ;
107+ }
108+
109+ if ( this . originalCursor ) {
110+ const markerManager = this . workspace . getMarkerManager ( ) ;
111+ markerManager . setCursor ( this . originalCursor ) ;
112+ }
113+
114+ this . workspace . setTheme ( this . originalTheme ) ;
115+
116+ this . navigationController . dispose ( ) ;
52117 }
53118
54119 /**
0 commit comments