Skip to content

Commit ae7a4d2

Browse files
feat(a11y): Add optional home/end key support to ListKeyManager
1 parent 298cdc0 commit ae7a4d2

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

src/cdk/a11y/key-manager/list-key-manager.spec.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, UP_ARROW} from '@angular/cdk/keycodes';
1+
import {DOWN_ARROW, END, HOME, LEFT_ARROW, RIGHT_ARROW, TAB, UP_ARROW} from '@angular/cdk/keycodes';
22
import {createKeyboardEvent} from '@angular/cdk/testing/private';
33
import {QueryList} from '@angular/core';
44
import {fakeAsync, tick} from '@angular/core/testing';
@@ -51,6 +51,8 @@ describe('Key managers', () => {
5151
leftArrow: KeyboardEvent,
5252
rightArrow: KeyboardEvent,
5353
tab: KeyboardEvent,
54+
home: KeyboardEvent,
55+
end: KeyboardEvent,
5456
unsupported: KeyboardEvent
5557
};
5658

@@ -62,6 +64,8 @@ describe('Key managers', () => {
6264
leftArrow: createKeyboardEvent('keydown', LEFT_ARROW),
6365
rightArrow: createKeyboardEvent('keydown', RIGHT_ARROW),
6466
tab: createKeyboardEvent('keydown', TAB),
67+
home: createKeyboardEvent('keydown', HOME),
68+
end: createKeyboardEvent('keydown', END),
6569
unsupported: createKeyboardEvent('keydown', 192) // corresponds to the tilde character (~)
6670
};
6771
});
@@ -195,6 +199,30 @@ describe('Key managers', () => {
195199
expect(fakeKeyEvents.downArrow.defaultPrevented).toBe(false);
196200
});
197201

202+
describe('withHomeAndEnd', () => {
203+
beforeEach(() => {
204+
keyManager.withHomeAndEnd();
205+
});
206+
207+
it('should focus the first item when Home is pressed', () => {
208+
keyManager.setActiveItem(1);
209+
expect(keyManager.activeItemIndex).toBe(1);
210+
211+
keyManager.onKeydown(fakeKeyEvents.home);
212+
213+
expect(keyManager.activeItemIndex).toBe(0);
214+
});
215+
216+
it('should focus the last item when End is pressed', () => {
217+
keyManager.setActiveItem(0);
218+
expect(keyManager.activeItemIndex).toBe(0);
219+
220+
keyManager.onKeydown(fakeKeyEvents.end);
221+
222+
expect(keyManager.activeItemIndex).toBe(itemList.items.length - 1);
223+
})
224+
});
225+
198226
describe('with `vertical` direction', function(this: KeyEventTestContext) {
199227
beforeEach(() => {
200228
keyManager.withVerticalOrientation();

src/cdk/a11y/key-manager/list-key-manager.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import {
1919
ZERO,
2020
NINE,
2121
hasModifierKey,
22+
HOME,
23+
END,
2224
} from '@angular/cdk/keycodes';
2325
import {debounceTime, filter, map, tap} from 'rxjs/operators';
2426

@@ -47,6 +49,7 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
4749
private _vertical = true;
4850
private _horizontal: 'ltr' | 'rtl' | null;
4951
private _allowedModifierKeys: ListKeyManagerModifierKey[] = [];
52+
private _homeAndEnd = false;
5053

5154
/**
5255
* Predicate function that can be used to check whether an item should be skipped
@@ -174,6 +177,15 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
174177
return this;
175178
}
176179

180+
/**
181+
* Configures the key manager to focus the first and last items
182+
* respectively when the Home key and End Key are pressed.
183+
*/
184+
withHomeAndEnd(): this {
185+
this._homeAndEnd = true;
186+
return this;
187+
}
188+
177189
/**
178190
* Sets the active item to the item at the index specified.
179191
* @param index The index of the item to be set as active.
@@ -244,6 +256,22 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
244256
return;
245257
}
246258

259+
case HOME:
260+
if (this._homeAndEnd && isModifierAllowed) {
261+
this.setFirstItemActive();
262+
break;
263+
} else {
264+
return;
265+
}
266+
267+
case END:
268+
if (this._homeAndEnd && isModifierAllowed) {
269+
this.setLastItemActive();
270+
break;
271+
} else {
272+
return;
273+
}
274+
247275
default:
248276
if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
249277
// Attempt to use the `event.key` which also maps it to the user's keyboard language,

0 commit comments

Comments
 (0)