7
7
*/
8
8
9
9
import { QueryList } from '@angular/core' ;
10
- import { Observable } from 'rxjs/Observable' ;
11
10
import { Subject } from 'rxjs/Subject' ;
12
11
import { Subscription } from 'rxjs/Subscription' ;
13
12
import { UP_ARROW , DOWN_ARROW , TAB , A , Z } from '@angular/cdk/keycodes' ;
@@ -29,14 +28,20 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
29
28
private _activeItemIndex = - 1 ;
30
29
private _activeItem : T ;
31
30
private _wrap = false ;
32
- private _nonNavigationKeyStream = new Subject < number > ( ) ;
31
+ private _letterKeyStream = new Subject < string > ( ) ;
33
32
private _typeaheadSubscription : Subscription ;
34
33
35
34
// Buffer for the letters that the user has pressed when the typeahead option is turned on.
36
- private _pressedInputKeys : number [ ] = [ ] ;
35
+ private _pressedLetters : string [ ] = [ ] ;
37
36
38
37
constructor ( private _items : QueryList < T > ) { }
39
38
39
+ /**
40
+ * Stream that emits any time the TAB key is pressed, so components can react
41
+ * when focus is shifted off of the list.
42
+ */
43
+ tabOut : Subject < void > = new Subject < void > ( ) ;
44
+
40
45
/**
41
46
* Turns on wrapping mode, which ensures that the active item will wrap to
42
47
* the other end of list when there are no more items in the given direction.
@@ -62,12 +67,11 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
62
67
// Debounce the presses of non-navigational keys, collect the ones that correspond to letters
63
68
// and convert those letters back into a string. Afterwards find the first item that starts
64
69
// with that string and select it.
65
- this . _typeaheadSubscription = RxChain . from ( this . _nonNavigationKeyStream )
66
- . call ( filter , keyCode => keyCode >= A && keyCode <= Z )
67
- . call ( doOperator , keyCode => this . _pressedInputKeys . push ( keyCode ) )
70
+ this . _typeaheadSubscription = RxChain . from ( this . _letterKeyStream )
71
+ . call ( doOperator , keyCode => this . _pressedLetters . push ( keyCode ) )
68
72
. call ( debounceTime , debounceInterval )
69
- . call ( filter , ( ) => this . _pressedInputKeys . length > 0 )
70
- . call ( map , ( ) => String . fromCharCode ( ... this . _pressedInputKeys ) )
73
+ . call ( filter , ( ) => this . _pressedLetters . length > 0 )
74
+ . call ( map , ( ) => this . _pressedLetters . join ( '' ) )
71
75
. subscribe ( inputString => {
72
76
const items = this . _items . toArray ( ) ;
73
77
@@ -78,7 +82,7 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
78
82
}
79
83
}
80
84
81
- this . _pressedInputKeys = [ ] ;
85
+ this . _pressedLetters = [ ] ;
82
86
} ) ;
83
87
84
88
return this ;
@@ -101,13 +105,22 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
101
105
switch ( event . keyCode ) {
102
106
case DOWN_ARROW : this . setNextItemActive ( ) ; break ;
103
107
case UP_ARROW : this . setPreviousItemActive ( ) ; break ;
108
+ case TAB : this . tabOut . next ( ) ; return ;
109
+ default :
110
+ if ( event . keyCode >= A && event . keyCode <= Z ) {
111
+ // Attempt to use the `event.key` which also maps it to the user's keyboard language,
112
+ // otherwise fall back to `keyCode` and `fromCharCode` which always resolve to English.
113
+ this . _letterKeyStream . next ( event . key ?
114
+ event . key . toLocaleUpperCase ( ) :
115
+ String . fromCharCode ( event . keyCode ) ) ;
116
+ }
104
117
105
118
// Note that we return here, in order to avoid preventing
106
- // the default action of unsupported keys.
107
- default : this . _nonNavigationKeyStream . next ( event . keyCode ) ; return ;
119
+ // the default action of non-navigational keys.
120
+ return ;
108
121
}
109
122
110
- this . _pressedInputKeys = [ ] ;
123
+ this . _pressedLetters = [ ] ;
111
124
event . preventDefault ( ) ;
112
125
}
113
126
@@ -150,14 +163,6 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
150
163
this . _activeItemIndex = index ;
151
164
}
152
165
153
- /**
154
- * Observable that emits any time the TAB key is pressed, so components can react
155
- * when focus is shifted off of the list.
156
- */
157
- get tabOut ( ) : Observable < void > {
158
- return filter . call ( this . _nonNavigationKeyStream , keyCode => keyCode === TAB ) ;
159
- }
160
-
161
166
/**
162
167
* This method sets the active item, given a list of items and the delta between the
163
168
* currently active item and the new active item. It will calculate differently
0 commit comments