Skip to content

Commit

Permalink
add aria-* attrs and keyboard bindings to datepicker input
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Mar 9, 2017
1 parent a489c03 commit 36ed4a7
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/lib/datepicker/datepicker-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {SimpleDate} from '../core/datetime/simple-date';
import {CalendarLocale} from '../core/datetime/calendar-locale';
import {Subscription} from 'rxjs';
import {MdInputContainer} from '../input/input-container';
import {DOWN_ARROW} from '../core/keyboard/keycodes';


export const MD_DATEPICKER_VALUE_ACCESSOR: any = {
Expand All @@ -28,8 +29,12 @@ export const MD_DATEPICKER_VALUE_ACCESSOR: any = {
selector: 'input[mdDatepicker], input[matDatepicker]',
providers: [MD_DATEPICKER_VALUE_ACCESSOR],
host: {
'[attr.aria-expanded]': '_datepicker?.opened || "false"',
'[attr.aria-haspopup]': 'true',
'[attr.aria-owns]': '_datepicker?.id',
'(input)': '_onChange($event.target.value)',
'(blur)': '_onTouched()',
'(keydown)': '_onKeydown($event)',
}
})
export class MdDatepickerInput implements AfterContentInit, ControlValueAccessor, OnDestroy {
Expand All @@ -40,7 +45,7 @@ export class MdDatepickerInput implements AfterContentInit, ControlValueAccessor
this._datepicker._registerInput(this);
}
}
private _datepicker: MdDatepicker;
_datepicker: MdDatepicker;

@Input()
get value(): SimpleDate {
Expand Down Expand Up @@ -107,4 +112,11 @@ export class MdDatepickerInput implements AfterContentInit, ControlValueAccessor
setDisabledState(disabled: boolean): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'disabled', disabled);
}

_onKeydown(event: KeyboardEvent) {
if (event.altKey && event.keyCode === DOWN_ARROW) {
this._datepicker.open();
event.preventDefault();
}
}
}
11 changes: 11 additions & 0 deletions src/lib/datepicker/datepicker-trigger.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
$mat-datepicker-trigger-icon-size: 24px !default;


.mat-datepicker-trigger {
display: inline-block;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="currentColor"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/></svg>') no-repeat;
background-size: contain;
height: $mat-datepicker-trigger-icon-size;
width: $mat-datepicker-trigger-icon-size;
vertical-align: middle;
}
26 changes: 26 additions & 0 deletions src/lib/datepicker/datepicker-trigger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {ChangeDetectionStrategy, Component, Input, ViewEncapsulation} from '@angular/core';
import {MdDatepicker} from './datepicker';


@Component({
moduleId: module.id,
selector: 'md-datepicker-trigger, mat-datepicker-trigger',
template: '',
styleUrls: ['datepicker-trigger.css'],
host: {
'[class.mat-datepicker-trigger]': 'true',
'(click)': '_open($event)',
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdDatepickerTrigger {
@Input('for') datepicker: MdDatepicker;

_open(event: Event): void {
if (this.datepicker) {
this.datepicker.open();
event.stopPropagation();
}
}
}
1 change: 1 addition & 0 deletions src/lib/datepicker/datepicker.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<md-calendar
[id]="id"
[class.mat-datepicker-touch]="touchUi"
[class.mat-datepicker-non-touch]="!touchUi"
[startAt]="startAt"
Expand Down
15 changes: 15 additions & 0 deletions src/lib/datepicker/datepicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import {MdDatepickerInput} from './datepicker-input';
import {CalendarLocale} from '../core/datetime/calendar-locale';


let datepickerUid = 0;


/** Component responsible for managing the datepicker popup/dialog. */
@Component({
moduleId: module.id,
Expand Down Expand Up @@ -62,6 +65,10 @@ export class MdDatepicker implements OnDestroy {

@Output() selectedChanged = new EventEmitter<SimpleDate>();

opened = false;

id = `md-datepicker-${datepickerUid++}`;

get _selected(): SimpleDate {
return this._datepickerInput ? this._datepickerInput.value : null;
}
Expand Down Expand Up @@ -112,6 +119,9 @@ export class MdDatepicker implements OnDestroy {
* @param touchUi Whether to use the touch UI.
*/
open(): void {
if (this.opened) {
return;
}
if (!this._datepickerInput) {
throw new MdError('Attempted to open an MdDatepicker with no associated input.');
}
Expand All @@ -121,10 +131,14 @@ export class MdDatepicker implements OnDestroy {
}

this.touchUi ? this._openAsDialog() : this._openAsPopup();
this.opened = true;
}

/** Close the calendar. */
close(): void {
if (!this.opened) {
return;
}
if (this._popupRef && this._popupRef.hasAttached()) {
this._popupRef.detach();
}
Expand All @@ -135,6 +149,7 @@ export class MdDatepicker implements OnDestroy {
if (this._calendarPortal && this._calendarPortal.isAttached) {
this._calendarPortal.detach();
}
this.opened = false;
}

/** Open the calendar as a dialog. */
Expand Down
6 changes: 6 additions & 0 deletions src/lib/input/input-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ export class MdInputContainer implements AfterContentInit {

@ContentChildren(MdHint) _hintChildren: QueryList<MdHint>;

@ViewChild('underline') _underlineRef: ElementRef;

ngAfterContentInit() {
if (!this._mdInputChild) {
throw new MdInputContainerMissingMdInputError();
Expand Down Expand Up @@ -381,4 +383,8 @@ export class MdInputContainer implements AfterContentInit {

this._mdInputChild.ariaDescribedby = ids.join(' ');
}

getPopupConnectionElementRef(): ElementRef {
return this._underlineRef;
}
}

0 comments on commit 36ed4a7

Please sign in to comment.