-
-
Save peterblazejewicz/2fc4a682e4ed1a56093ac04f7a67b480 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 38488c5e1e297f362c2ff50b9e1b0decb6c8aa6a | |
Author: Peter Blazejewicz <peterblazejewicz@users.noreply.github.com> | |
Date: Sun Sep 22 12:39:29 2019 +0200 | |
chore(commit): fix | |
diff --git a/src/datepicker/datepicker-input.ts b/src/datepicker/datepicker-input.ts | |
index 08026a6..7ecc1d8 100644 | |
--- a/src/datepicker/datepicker-input.ts | |
+++ b/src/datepicker/datepicker-input.ts | |
@@ -441,6 +441,11 @@ export class NgbInputDatepicker implements OnChanges, | |
this.close(); | |
} | |
}); | |
+ datepickerInstance.close.subscribe((event: KeyboardEvent) => { | |
+ if (this.autoClose && this.isOpen()) { | |
+ this.close(); | |
+ } | |
+ }); | |
} | |
private _writeModelValue(model: NgbDate) { | |
diff --git a/src/datepicker/datepicker-keymap-service.spec.ts b/src/datepicker/datepicker-keymap-service.spec.ts | |
index a3269ae..777c8d2 100644 | |
--- a/src/datepicker/datepicker-keymap-service.spec.ts | |
+++ b/src/datepicker/datepicker-keymap-service.spec.ts | |
@@ -14,14 +14,14 @@ describe('ngb-datepicker-keymap-service', () => { | |
let service: NgbDatepickerKeyMapService; | |
let calendar: NgbCalendar; | |
- let mock: {focus, focusMove, focusSelect, model$}; | |
+ let mock: {focus, focusMove, focusSelect, close, model$}; | |
beforeEach(() => { | |
TestBed.configureTestingModule({ | |
providers: [ | |
NgbDatepickerKeyMapService, {provide: NgbCalendar, useClass: NgbCalendarGregorian}, { | |
provide: NgbDatepickerService, | |
- useValue: {focus: () => {}, focusMove: () => {}, focusSelect: () => {}, model$: new Subject()} | |
+ useValue: {focus: () => {}, focusMove: () => {}, focusSelect: () => {}, close: () => {}, model$: new Subject()} | |
} | |
] | |
}); | |
@@ -33,6 +33,7 @@ describe('ngb-datepicker-keymap-service', () => { | |
spyOn(mock, 'focus'); | |
spyOn(mock, 'focusMove'); | |
spyOn(mock, 'focusSelect'); | |
+ spyOn(mock, 'close'); | |
}); | |
it('should be instantiated', () => { expect(service).toBeTruthy(); }); | |
@@ -120,6 +121,15 @@ describe('ngb-datepicker-keymap-service', () => { | |
expect(e.preventDefault).toHaveBeenCalled(); | |
expect(e.stopPropagation).toHaveBeenCalled(); | |
+ // ESC | |
+ e = event(Key.Escape); | |
+ spyOn(e, 'preventDefault'); | |
+ spyOn(e, 'stopPropagation'); | |
+ | |
+ service.processKey(e); | |
+ expect(e.preventDefault).toHaveBeenCalled(); | |
+ expect(e.stopPropagation).toHaveBeenCalled(); | |
+ | |
// unknown key | |
e = event(23); | |
spyOn(e, 'preventDefault'); | |
diff --git a/src/datepicker/datepicker-keymap-service.ts b/src/datepicker/datepicker-keymap-service.ts | |
index 0bf6769..4333ccf 100644 | |
--- a/src/datepicker/datepicker-keymap-service.ts | |
+++ b/src/datepicker/datepicker-keymap-service.ts | |
@@ -51,6 +51,9 @@ export class NgbDatepickerKeyMapService { | |
case Key.Space: | |
this._service.focusSelect(); | |
break; | |
+ case Key.Escape: | |
+ this._service.close(event); | |
+ break; | |
default: | |
return; | |
} | |
diff --git a/src/datepicker/datepicker-service.spec.ts b/src/datepicker/datepicker-service.spec.ts | |
index 0538876..cc1854d 100644 | |
--- a/src/datepicker/datepicker-service.spec.ts | |
+++ b/src/datepicker/datepicker-service.spec.ts | |
@@ -6,6 +6,7 @@ import {Subscription} from 'rxjs'; | |
import {DatepickerViewModel} from './datepicker-view-model'; | |
import {NgbDatepickerI18n, NgbDatepickerI18nDefault} from './datepicker-i18n'; | |
import {Type} from '@angular/core'; | |
+import {Key} from '../util/key'; | |
describe('ngb-datepicker-service', () => { | |
@@ -15,6 +16,8 @@ describe('ngb-datepicker-service', () => { | |
let mock: {onNext}; | |
let selectDate: NgbDate; | |
let mockSelect: {onNext}; | |
+ let mockClose: {onNext}; | |
+ let closeEvent: KeyboardEvent; | |
let subscriptions: Subscription[]; | |
@@ -35,6 +38,7 @@ describe('ngb-datepicker-service', () => { | |
subscriptions = []; | |
model = undefined; | |
selectDate = null; | |
+ closeEvent = undefined; | |
mock = {onNext: () => {}}; | |
spyOn(mock, 'onNext'); | |
@@ -42,10 +46,14 @@ describe('ngb-datepicker-service', () => { | |
mockSelect = {onNext: () => {}}; | |
spyOn(mockSelect, 'onNext'); | |
+ mockClose = {onNext: () => {}}; | |
+ spyOn(mockClose, 'onNext'); | |
+ | |
// subscribing | |
subscriptions.push( | |
service.model$.subscribe(mock.onNext), service.model$.subscribe(m => model = m), | |
- service.select$.subscribe(mockSelect.onNext), service.select$.subscribe(d => selectDate = d)); | |
+ service.select$.subscribe(mockSelect.onNext), service.select$.subscribe(d => selectDate = d), | |
+ service.close$.subscribe(mockClose.onNext), service.close$.subscribe(e => closeEvent = e)); | |
}); | |
afterEach(() => { subscriptions.forEach(s => s.unsubscribe()); }); | |
@@ -953,6 +961,25 @@ describe('ngb-datepicker-service', () => { | |
}); | |
}); | |
+ describe('close handling', () => { | |
+ | |
+ const event = (type: string, keyCode: number, shift = false) => | |
+ <any>({type, which: keyCode, shiftKey: shift, preventDefault: () => {}, stopPropagation: () => {}}); | |
+ | |
+ it(`should emit keyboard event on Escape key down`, () => { | |
+ const mockEvent = event('keydown', Key.Escape); | |
+ service.close(mockEvent); | |
+ expect(mockClose.onNext).toHaveBeenCalledTimes(1); | |
+ expect(mockEvent).toBe(closeEvent); | |
+ }); | |
+ | |
+ it(`should not emit keyboard event when not Escape or key down`, () => { | |
+ service.close(event('keyup', Key.ArrowLeft)); | |
+ expect(mockClose.onNext).toHaveBeenCalledTimes(0); | |
+ }); | |
+ | |
+ }); | |
+ | |
describe(`focus handling`, () => { | |
it(`should generate 1 month on 'focus()' by default`, () => { | |
diff --git a/src/datepicker/datepicker-service.ts b/src/datepicker/datepicker-service.ts | |
index 88b0665..720714d 100644 | |
--- a/src/datepicker/datepicker-service.ts | |
+++ b/src/datepicker/datepicker-service.ts | |
@@ -20,6 +20,7 @@ import { | |
import {filter} from 'rxjs/operators'; | |
import {NgbDatepickerI18n} from './datepicker-i18n'; | |
+import { Key } from '../util/key'; | |
@Injectable() | |
export class NgbDatepickerService { | |
@@ -27,6 +28,8 @@ export class NgbDatepickerService { | |
private _select$ = new Subject<NgbDate>(); | |
+ private _close$ = new Subject<KeyboardEvent>(); | |
+ | |
private _state: DatepickerViewModel = { | |
disabled: false, | |
displayMonths: 1, | |
@@ -45,6 +48,8 @@ export class NgbDatepickerService { | |
get select$(): Observable<NgbDate> { return this._select$.pipe(filter(date => date !== null)); } | |
+ get close$(): Observable<KeyboardEvent> { return this._close$.pipe(filter(event => event.which === Key.Escape)); } | |
+ | |
set dayTemplateData(dayTemplateData: NgbDayTemplateData) { | |
if (this._state.dayTemplateData !== dayTemplateData) { | |
this._nextState({dayTemplateData}); | |
@@ -127,6 +132,12 @@ export class NgbDatepickerService { | |
} | |
} | |
+ close(event: KeyboardEvent) { | |
+ if(event.type === 'keydown' && event.which === Key.Escape) { | |
+ this._close$.next(event); | |
+ } | |
+ } | |
+ | |
open(date: NgbDate) { | |
const firstDate = this.toValidDate(date, this._calendar.getToday()); | |
if (!this._state.disabled && (!this._state.firstDate || isChangedMonth(this._state.firstDate, date))) { | |
diff --git a/src/datepicker/datepicker.ts b/src/datepicker/datepicker.ts | |
index a17e658..fc04226 100644 | |
--- a/src/datepicker/datepicker.ts | |
+++ b/src/datepicker/datepicker.ts | |
@@ -242,6 +242,11 @@ export class NgbDatepicker implements OnDestroy, | |
*/ | |
@Output() select = new EventEmitter<NgbDate>(); | |
+ /** | |
+ * An event emitted when user press down ESC key | |
+ */ | |
+ @Output() close = new EventEmitter<KeyboardEvent>(); | |
+ | |
onChange = (_: any) => {}; | |
onTouched = () => {}; | |
@@ -296,6 +301,11 @@ export class NgbDatepicker implements OnDestroy, | |
_cd.markForCheck(); | |
}); | |
+ | |
+ _service.close$.pipe(takeUntil(this._destroyed$)).subscribe(event => { | |
+ this.close.emit(event); | |
+ }); | |
+ | |
} | |
focus() { | |
diff --git a/src/modal/modal-window.spec.ts b/src/modal/modal-window.spec.ts | |
index 2f55d07..c91a2ec 100644 | |
--- a/src/modal/modal-window.spec.ts | |
+++ b/src/modal/modal-window.spec.ts | |
@@ -105,7 +105,7 @@ describe('ngb-modal-dialog', () => { | |
done(); | |
}); | |
- fixture.debugElement.triggerEventHandler('keyup.esc', {}); | |
+ fixture.debugElement.triggerEventHandler('keydown.esc', {}); | |
}); | |
}); | |
diff --git a/src/modal/modal-window.ts b/src/modal/modal-window.ts | |
index 9ea8a5f..be7c253 100644 | |
--- a/src/modal/modal-window.ts | |
+++ b/src/modal/modal-window.ts | |
@@ -21,7 +21,7 @@ import {ModalDismissReasons} from './modal-dismiss-reasons'; | |
'[class]': '"modal fade show d-block" + (windowClass ? " " + windowClass : "")', | |
'role': 'dialog', | |
'tabindex': '-1', | |
- '(keyup.esc)': 'escKey($event)', | |
+ '(keydown.esc)': 'escKey($event)', | |
'(click)': 'backdropClick($event)', | |
'[attr.aria-modal]': 'true', | |
'[attr.aria-labelledby]': 'ariaLabelledBy', | |
diff --git a/src/modal/modal.spec.ts b/src/modal/modal.spec.ts | |
index 80af80c..865d843 100644 | |
--- a/src/modal/modal.spec.ts | |
+++ b/src/modal/modal.spec.ts | |
@@ -350,12 +350,12 @@ describe('ngb-modal', () => { | |
expect(fixture.nativeElement).toHaveModal(['foo', 'bar']); | |
expect(document.activeElement).toBe(ngbModalWindow2); | |
- (<DebugElement>getDebugNode(document.activeElement)).triggerEventHandler('keyup.esc', {}); | |
+ (<DebugElement>getDebugNode(document.activeElement)).triggerEventHandler('keydown.esc', {}); | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).toHaveModal(['foo']); | |
expect(document.activeElement).toBe(ngbModalWindow1); | |
- (<DebugElement>getDebugNode(document.activeElement)).triggerEventHandler('keyup.esc', {}); | |
+ (<DebugElement>getDebugNode(document.activeElement)).triggerEventHandler('keydown.esc', {}); | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).not.toHaveModal(); | |
expect(document.activeElement).toBe(document.body); | |
@@ -575,7 +575,7 @@ describe('ngb-modal', () => { | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).toHaveModal('foo'); | |
- (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keyup.esc', {}); | |
+ (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keydown.esc', {}); | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).not.toHaveModal(); | |
}); | |
@@ -585,7 +585,7 @@ describe('ngb-modal', () => { | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).toHaveModal('foo'); | |
- (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keyup.esc', {}); | |
+ (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keydown.esc', {}); | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).toHaveModal(); | |
@@ -599,7 +599,7 @@ describe('ngb-modal', () => { | |
fixture.detectChanges(); | |
expect(fixture.nativeElement).toHaveModal('foo'); | |
- (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keyup.esc', { | |
+ (<DebugElement>getDebugNode(document.querySelector('ngb-modal-window'))).triggerEventHandler('keydown.esc', { | |
defaultPrevented: true | |
}); | |
fixture.detectChanges(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment