Skip to content

Commit 9ea0a03

Browse files
committed
fix(date-time-picker): use event.key for keyboad navigation
previous implementation used deprecated event.code
1 parent 26a3403 commit 9ea0a03

14 files changed

+113
-68
lines changed

Diff for: README.md

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Native Angular (5+) datetime picker component styled by Twitter Bootstrap 4.
1818

1919
[Demo Page](https://angular-bootstrap-datetimepicker.stackblitz.io/)
2020

21+
[Github](https://github.com/dalelotts/angular-bootstrap-datetimepicker)
22+
2123

2224
*Read this in other languages: [Spanish](https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/README.es_MX.md)*
2325
## On Angular 1.x?

Diff for: src/index.html

+1-4
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,12 @@
4343
</nav>
4444
</header>
4545
<section id="content" class="container mt-2">
46-
<app-root>Loading...</app-root>
46+
<dl-root>Loading...</dl-root>
4747
</section>
4848

4949
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
5050
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
5151
crossorigin="anonymous"></script>
52-
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
53-
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
54-
crossorigin="anonymous"></script>
5552
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
5653
integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
5754
crossorigin="anonymous"></script>
+29-17
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,47 @@
1-
This directive provides all of the user facing functionality to input dates and/or times. |
1+
This directive provides all of the user facing functionality to input a date and/or time using the keyboard. |
22

3-
## Supported date types
3+
## Model date types
44

55
Import the module corresponding to the desired data type of the date in the model.
6-
* Native JavaScript Date: import 'DlDateTimeInputDateModule'
7-
* Moment Date: import 'DlDateTimeInputMomentModule'
8-
* Milliseconds (local): import 'DlDateTimeInputNumberModule'
9-
* String (local): import 'DlDateTimePInputStringModule'
6+
* Native JavaScript Date: import `DlDateTimePickerDateModule`
7+
* Moment Date: import `DlDateTimePickerMomentModule`
8+
* Milliseconds (local): import `DlDateTimePickerNumberModule`
9+
* String (local): import `DlDateTimePickerStringModule`
1010

1111
A `DateAdapter` is used to adapt the data type in the model to the `number` data type
12-
used internally by the date/time input directive.
12+
used internally by the date/time picker.
1313

1414
If you need a different data type than what is currently supported, you can extend
1515
`DlDateAdapter<D>` to provide the data type you need then override the `DlDateAdapter`
1616
provider in `app.module.ts` to use your new class.
1717

1818
`providers: [{provide: DlDateAdapter, useClass: MyCustomDateAdapter}],`
1919

20-
### String Date Adapter Formats
21-
The display, input and `model` formats for dates are injected using the
22-
`DL_DATE_TIME_DISPLAY_FORMAT`, `DL_STRING_DATE_MODEL_FORMAT` and `DL_DATE_TIME_INPUT_FORMATS` tokens.
20+
## Display format
2321

24-
`DL_DEFAULT_DATE_TIME_FORMAT` defaults to `moment`'s `lll` long date format.
25-
This is the default display format for this directive.
22+
The display format is defined in the `DL_DATE_TIME_DISPLAY_FORMAT` token and is injected into this component
23+
to control the display format.
2624

27-
If you want a different display, override the injection token in `app.module.ts`
28-
i.e `{provide: DL_DATE_TIME_DISPLAY_FORMAT, useValue: '<what ever format you want goes here>'}`
25+
`DL_DATE_TIME_DISPLAY_FORMAT` defaults to `moment`'s `lll` long date format.
26+
Override `DL_DATE_TIME_DISPLAY_FORMAT` if you do not like the default format.
2927

30-
**Nota bene** For convenience `DL_DATE_TIME_INPUT_FORMATS` defaults to multiple formats,
31-
which can dramatically slow down paring performance. Consider overriding this token to only include
32-
the formats required by your project.
28+
`{provide: DL_DATE_TIME_DISPLAY_FORMAT, useValue: '<what ever format you want goes here>'}`
29+
30+
## Input formats
31+
32+
This directive supports multiple input formats, as defined in the `DL_DATE_TIME_INPUT_FORMATS` token.
33+
When the user inputs a string value into a text box, this directive attempts to parse the input
34+
using one of the specified formats, in the order the format occur in the array.
35+
36+
Once one of the formats is able to parse the user input, the date is set in the model.
37+
38+
**Nota bene** For convenience `DL_DATE_TIME_INPUT_FORMATS` defaults to support multiple formats,
39+
which can dramatically slow down paring performance. It can also result is successfully parsing
40+
a date using a format that is not appropriate for your use case.
41+
42+
Consider overriding the `DL_DATE_TIME_INPUT_FORMATS` token to only include only the specific formats required by your project.
43+
44+
`{provide: DL_DATE_TIME_INPUT_FORMATS, useValue: ['<input format zero>', ..., '<input format N>']}`
3345

3446
See moment's [parsing multiple formats](https://momentjs.com/guides/#/parsing/multiple-formats/)
3547
page for more information on how these date formats are used.

Diff for: src/lib/dl-date-time-input/dl-date-time-input.directive.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ const moment = _moment;
2424
const alwaysTrueInputFilter: (value: any) => boolean = () => true;
2525

2626
/**
27-
* This directive allows the user to input dates into an input and store a date value in various formats.
27+
* This directive allows the user to enter dates, using the keyboard, into an input box and
28+
* angular will then store a date value in the model.
29+
*
30+
* The input format(s), display format, and model format are independent and fully customizable.
2831
*/
2932
@Directive({
3033
selector: 'input[dlDateTimeInput]',
@@ -68,9 +71,9 @@ export class DlDateTimeInputDirective<D> implements ControlValueAccessor, Valida
6871
* @param _dateAdapter
6972
* date adapter for the date type in the model.
7073
* @param _displayFormat
71-
* the format to use for a valid date/time value.
74+
* from `DL_DATE_TIME_DISPLAY_FORMAT`, which defines the format to use for a valid date/time value.
7275
* @param _inputFormats
73-
* the input formats that allowed as valid date/time values.
76+
* from `DL_DATE_TIME_INPUT_FORMATS`, which defines the input formats that allowed as valid date/time values.
7477
* NB: moment is always in strict parse mode for this directive.
7578
*/
7679
constructor(

Diff for: src/lib/dl-date-time-picker/dl-date-time-picker.component.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ The following keyboard shortcuts are supported in in all views:
1818
## Supported date types
1919

2020
Import the module corresponding to the desired data type of the date in the model.
21-
* Native JavaScript Date: import 'DlDateTimePickerDateModule'
22-
* Moment Date: import 'DlDateTimePickerMomentModule'
23-
* Milliseconds (local): import 'DlDateTimePickerNumberModule'
24-
* String (local): import 'DlDateTimePickerStringModule'
21+
* Native JavaScript Date: import `DlDateTimePickerDateModule`
22+
* Moment Date: import `DlDateTimePickerMomentModule`
23+
* Milliseconds (local): import `DlDateTimePickerNumberModule`
24+
* String (local): import `DlDateTimePickerStringModule`
2525

2626
A `DateAdapter` is used to adapt the data type in the model to the `number` data type
2727
used internally by the date/time picker.

Diff for: src/lib/dl-date-time-picker/dl-date-time-picker.component.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ const moment = _moment;
5858
**/
5959

6060
const keyCodeToModelProviderMethod = {
61+
'ArrowDown': 'goDown',
62+
'ArrowLeft': 'goLeft',
63+
'ArrowRight': 'goRight',
64+
'ArrowUp': 'goUp',
65+
'Down': 'goDown',
66+
'End': 'goEnd',
67+
'Home': 'goHome',
68+
'Left': 'goLeft',
69+
'PageDown': 'pageDown',
70+
'PageUp': 'pageUp',
71+
'Right': 'goRight',
72+
'Up': 'goUp',
6173
33: 'pageUp',
6274
34: 'pageDown',
6375
35: 'goEnd',
@@ -152,7 +164,7 @@ export class DlDateTimePickerComponent<D> implements OnChanges, OnInit, ControlV
152164
* Maps view name to the model provider for that view.
153165
* @internal
154166
**/
155-
private _viewToModelProvider: {
167+
private readonly _viewToModelProvider: {
156168
year: DlModelProvider;
157169
month: DlModelProvider;
158170
day: DlModelProvider;
@@ -288,6 +300,7 @@ export class DlDateTimePickerComponent<D> implements OnChanges, OnInit, ControlV
288300
minute: minuteModelComponent,
289301
};
290302
}
303+
291304
/* tslint:enable:member-ordering */
292305
/**
293306
* Set's the model for the current view after applying the selection filter.
@@ -500,7 +513,9 @@ export class DlDateTimePickerComponent<D> implements OnChanges, OnInit, ControlV
500513
* @internal
501514
**/
502515
_handleKeyDown($event: KeyboardEvent): void {
503-
const functionName = keyCodeToModelProviderMethod[$event.code];
516+
const functionName = keyCodeToModelProviderMethod[$event.key];
517+
518+
console.log($event, functionName);
504519

505520
if (functionName) {
506521
const modelProvider = this._viewToModelProvider[this._model.viewName];

Diff for: src/lib/dl-date-time-picker/specs/dispatch-events.ts

+21-21
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
* found in the LICENSE file at https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/LICENSE
88
*/
99

10-
export const ENTER = 13;
11-
export const SPACE = 32;
12-
export const PAGE_UP = 33;
13-
export const PAGE_DOWN = 34;
14-
export const END = 35;
15-
export const HOME = 36;
16-
export const UP_ARROW = 38;
17-
export const DOWN_ARROW = 40;
18-
export const RIGHT_ARROW = 39;
19-
export const LEFT_ARROW = 37;
10+
export const ENTER = 'Enter';
11+
export const SPACE = ' ';
12+
export const PAGE_UP = 'PageUp';
13+
export const PAGE_DOWN = 'PageDown';
14+
export const END = 'End';
15+
export const HOME = 'Home';
16+
export const UP_ARROW = 'ArrowUp';
17+
export const DOWN_ARROW = 'ArrowDown';
18+
export const RIGHT_ARROW = 'ArrowRight';
19+
export const LEFT_ARROW = 'ArrowLeft';
2020

2121
/** Utility to dispatch any event on a Node. */
2222
export function dispatchEvent(node: Node | Window, event: Event): Event {
@@ -25,30 +25,30 @@ export function dispatchEvent(node: Node | Window, event: Event): Event {
2525
}
2626

2727
/** Shorthand to dispatch a keyboard event with a specified key code. */
28-
export function dispatchKeyboardEvent(node: Node, type: string, keyCode: number, key?: string, target?: Element): KeyboardEvent {
29-
return dispatchEvent(node, createKeyboardEvent(type, keyCode, target, key)) as KeyboardEvent;
28+
export function dispatchKeyboardEvent(node: Node, type: string, key: string, target?: Element): KeyboardEvent {
29+
return dispatchEvent(node, createKeyboardEvent(type, key, target)) as KeyboardEvent;
3030
}
3131

3232
/** Dispatches a keydown event from an element. */
33-
export function createKeyboardEvent(type: string, keyCode: number, target?: Element, key?: string) {
33+
export function createKeyboardEvent(type: string, key: string, target?: Element) {
3434
const event = new KeyboardEvent(type, {
3535
bubbles: true,
3636
key: key,
37-
code: keyCode.toString(10),
37+
code: key,
3838
cancelable: true,
3939
});
4040

4141
// // Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`.
4242
// const initEventFn = (event.initKeyEvent || event.initKeyboardEvent).bind(event);
4343
const originalPreventDefault = event.preventDefault;
4444

45-
// Webkit Browsers don't set the keyCode when calling the init function.
46-
// See related bug https://bugs.webkit.org/show_bug.cgi?id=16735
47-
Object.defineProperties(event, {
48-
keyCode: {get: () => keyCode},
49-
key: {get: () => key},
50-
target: {get: () => target}
51-
});
45+
// // Webkit Browsers don't set the keyCode when calling the init function.
46+
// // See related bug https://bugs.webkit.org/show_bug.cgi?id=16735
47+
// Object.defineProperties(event, {
48+
// keyCode: {get: () => keyCode},
49+
// key: {get: () => key},
50+
// target: {get: () => target}
51+
// });
5252

5353
// IE won't set `defaultPrevented` on synthetic events so we need to do it manually.
5454
event.preventDefault = function () {

Diff for: src/lib/dl-date-time-picker/specs/ng-model/ng-model.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ describe('DlDateTimePickerComponent', () => {
134134

135135
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
136136

137-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
137+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
138138
fixture.detectChanges();
139139

140140
expect(component.picker.value).not.toBeNull();
@@ -152,7 +152,7 @@ describe('DlDateTimePickerComponent', () => {
152152

153153
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
154154

155-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
155+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
156156
fixture.detectChanges();
157157

158158
expect(component.picker.value).not.toBeNull();

Diff for: src/lib/dl-date-time-picker/specs/start-view/day-view.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,7 @@ describe('DlDateTimePickerComponent startView=day', () => {
489489
let activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
490490
expect(activeElement.nativeElement.textContent).toBe('11');
491491

492-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 65); // A
492+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 'A'); // A
493493
fixture.detectChanges();
494494

495495
activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
@@ -499,7 +499,7 @@ describe('DlDateTimePickerComponent startView=day', () => {
499499
it('should change to .dl-abdtp-hour-view when hitting ENTER', () => {
500500
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
501501

502-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
502+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
503503
fixture.detectChanges();
504504

505505
const dayView = fixture.debugElement.query(By.css('.dl-abdtp-day-view'));
@@ -512,7 +512,7 @@ describe('DlDateTimePickerComponent startView=day', () => {
512512
it('should change to .dl-abdtp-hour-view when hitting SPACE', () => {
513513
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
514514

515-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
515+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
516516
fixture.detectChanges();
517517

518518
const dayView = fixture.debugElement.query(By.css('.dl-abdtp-day-view'));

Diff for: src/lib/dl-date-time-picker/specs/start-view/hour-view.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ describe('DlDateTimePickerComponent startView=hour', () => {
449449
let activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
450450
expect(activeElement.nativeElement.textContent).toBe('3:00 PM');
451451

452-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 65); // A
452+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 'A');
453453
fixture.detectChanges();
454454

455455
activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
@@ -459,7 +459,7 @@ describe('DlDateTimePickerComponent startView=hour', () => {
459459
it('should change to .dl-abdtp-minute-view when hitting ENTER', () => {
460460
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
461461

462-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
462+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
463463
fixture.detectChanges();
464464

465465
const hourView = fixture.debugElement.query(By.css('.dl-abdtp-hour-view'));
@@ -472,7 +472,7 @@ describe('DlDateTimePickerComponent startView=hour', () => {
472472
it('should change to .dl-abdtp-minute-view when hitting SPACE', () => {
473473
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
474474

475-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
475+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
476476
fixture.detectChanges();
477477

478478
const hourView = fixture.debugElement.query(By.css('.dl-abdtp-hour-view'));

Diff for: src/lib/dl-date-time-picker/specs/start-view/minute-view.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ describe('DlDateTimePickerComponent startView=minute', () => {
471471
let activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
472472
expect(activeElement.nativeElement.textContent).toBe('3:50 PM');
473473

474-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 65); // A
474+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 'A');
475475
fixture.detectChanges();
476476

477477
activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
@@ -484,7 +484,7 @@ describe('DlDateTimePickerComponent startView=minute', () => {
484484

485485
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
486486

487-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
487+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
488488
fixture.detectChanges();
489489

490490
const minuteView = fixture.debugElement.query(By.css('.dl-abdtp-minute-view'));
@@ -499,7 +499,7 @@ describe('DlDateTimePickerComponent startView=minute', () => {
499499

500500
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
501501

502-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
502+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
503503
fixture.detectChanges();
504504

505505
const minuteView = fixture.debugElement.query(By.css('.dl-abdtp-minute-view'));

Diff for: src/lib/dl-date-time-picker/specs/start-view/month-view.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ describe('DlDateTimePickerComponent startView=month', () => {
450450
let activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
451451
expect(activeElement.nativeElement.textContent).toBe('Dec');
452452

453-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 65); // A
453+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 'A');
454454
fixture.detectChanges();
455455

456456
activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
@@ -460,7 +460,7 @@ describe('DlDateTimePickerComponent startView=month', () => {
460460
it('should change to .dl-abdtp-day-view when hitting ENTER', () => {
461461
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
462462

463-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
463+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
464464
fixture.detectChanges();
465465

466466
const monthView = fixture.debugElement.query(By.css('.dl-abdtp-month-view'));
@@ -473,7 +473,7 @@ describe('DlDateTimePickerComponent startView=month', () => {
473473
it('should change to .dl-abdtp-day-view when hitting SPACE', () => {
474474
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
475475

476-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
476+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
477477
fixture.detectChanges();
478478

479479
const monthView = fixture.debugElement.query(By.css('.dl-abdtp-month-view'));

Diff for: src/lib/dl-date-time-picker/specs/start-view/year-view.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ describe('DlDateTimePickerComponent', () => {
279279
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
280280
expect(activeElement.nativeElement.textContent).toBe('2017');
281281

282-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 65); // A
282+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', 'A');
283283
fixture.detectChanges();
284284

285285
expect(activeElement.nativeElement.textContent).toBe('2017');
@@ -288,7 +288,7 @@ describe('DlDateTimePickerComponent', () => {
288288
it('should change to .dl-abdtp-month-view when hitting ENTER', () => {
289289
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
290290

291-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER, 'enter');
291+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', ENTER);
292292
fixture.detectChanges();
293293

294294
const monthView = fixture.debugElement.query(By.css('.dl-abdtp-month-view'));
@@ -304,7 +304,7 @@ describe('DlDateTimePickerComponent', () => {
304304

305305
const activeElement = fixture.debugElement.query(By.css('.dl-abdtp-active'));
306306

307-
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE, 'space');
307+
dispatchKeyboardEvent(activeElement.nativeElement, 'keydown', SPACE);
308308
fixture.detectChanges();
309309

310310
const monthView = fixture.debugElement.query(By.css('.dl-abdtp-month-view'));

0 commit comments

Comments
 (0)