Skip to content

Commit

Permalink
addressed comments
Browse files Browse the repository at this point in the history
  • Loading branch information
mmalerba committed Nov 10, 2016
1 parent 33d02c6 commit b12a7c6
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 44 deletions.
32 changes: 6 additions & 26 deletions src/lib/core/a11y/focus-trap.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
import {
Component,
ViewEncapsulation,
ViewChild,
ElementRef,
Input,
AfterContentInit,
NgZone
} from '@angular/core';
import {Component, ViewEncapsulation, ViewChild, ElementRef, Input, NgZone} from '@angular/core';
import {InteractivityChecker} from './interactivity-checker';
import {coerceBooleanProperty} from '../coersion/boolean-property';

Expand All @@ -29,29 +21,17 @@ import {coerceBooleanProperty} from '../coersion/boolean-property';
<div *ngIf="active" tabindex="0" (focus)="focusFirstTabbableElement()"></div>`,
encapsulation: ViewEncapsulation.None,
})
export class FocusTrap implements AfterContentInit {
export class FocusTrap {
@ViewChild('trappedContent') trappedContent: ElementRef;

@Input()
get active(): boolean { return this._active; }
set active(val: boolean) { this._active = coerceBooleanProperty(val); }

/** Whether the DOM content is ready. */
private _contentReady: boolean = false;

/** Whether the focus trap is active. */
private _active: boolean = true;
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(val: boolean) { this._disabled = coerceBooleanProperty(val); }
private _disabled: boolean = false;

constructor(private _checker: InteractivityChecker, private _ngZone: NgZone) { }

ngAfterContentInit() {
this._contentReady = true;
// Trigger setter behavior.
if (this.active) {

}
}

/**
* Waits for microtask queue to empty, then focuses the first tabbable element within the focus
* trap region.
Expand Down
28 changes: 14 additions & 14 deletions src/lib/sidenav/sidenav.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,49 +256,49 @@ describe('MdSidenav', () => {
let fixture: ComponentFixture<SidenavWitFocusableElements>;
let testComponent: SidenavWitFocusableElements;
let sidenav: MdSidenav;
let link1Element: HTMLElement;
let link2Element: HTMLElement;
let firstFocusableElement: HTMLElement;
let lastFocusableElement: HTMLElement;

beforeEach(() => {
fixture = TestBed.createComponent(SidenavWitFocusableElements);
testComponent = fixture.debugElement.componentInstance;
sidenav = fixture.debugElement.query(By.directive(MdSidenav)).componentInstance;
link1Element = fixture.debugElement.query(By.css('.link1')).nativeElement;
link2Element = fixture.debugElement.query(By.css('.link1')).nativeElement;
link2Element.focus();
firstFocusableElement = fixture.debugElement.query(By.css('.link1')).nativeElement;
lastFocusableElement = fixture.debugElement.query(By.css('.link1')).nativeElement;
lastFocusableElement.focus();
});

it('should trp focus when opened in "over" mode', fakeAsync(() => {
it('should trap focus when opened in "over" mode', fakeAsync(() => {
testComponent.mode = 'over';
link2Element.focus();
lastFocusableElement.focus();

sidenav.open();
endSidenavTransition(fixture);
tick();

expect(document.activeElement).toBe(link1Element);
expect(document.activeElement).toBe(firstFocusableElement);
}));

it('should trap tabs when opened in "push" mode', fakeAsync(() => {
it('should trap focus when opened in "push" mode', fakeAsync(() => {
testComponent.mode = 'push';
link2Element.focus();
lastFocusableElement.focus();

sidenav.open();
endSidenavTransition(fixture);
tick();

expect(document.activeElement).toBe(link1Element);
expect(document.activeElement).toBe(firstFocusableElement);
}));

it('should not trap tabs when opened in "side" mode', fakeAsync(() => {
it('should not trap focus when opened in "side" mode', fakeAsync(() => {
testComponent.mode = 'side';
link2Element.focus();
lastFocusableElement.focus();

sidenav.open();
endSidenavTransition(fixture);
tick();

expect(document.activeElement).toBe(link2Element);
expect(document.activeElement).toBe(lastFocusableElement);
}));
});
});
Expand Down
9 changes: 5 additions & 4 deletions src/lib/sidenav/sidenav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class MdDuplicatedSidenavError extends MdError {
@Component({
moduleId: module.id,
selector: 'md-sidenav',
template: '<focus-trap [active]="focusTrapActive"><ng-content></ng-content></focus-trap>',
template: '<focus-trap [disabled]="isFocusTrapDisabled"><ng-content></ng-content></focus-trap>',
host: {
'(transitionend)': '_onTransitionEnd($event)',
// must prevent the browser from aligning text based on value
Expand Down Expand Up @@ -111,8 +111,9 @@ export class MdSidenav implements AfterContentInit {
/** Event emitted when the sidenav alignment changes. */
@Output('align-changed') onAlignChanged = new EventEmitter<void>();

get focusTrapActive() {
return this.opened && this.mode != 'side';
get isFocusTrapDisabled() {
// The focus trap is only enabled when the sidenav is open in any mode other than side.
return !this.opened || this.mode == 'side';
}

/**
Expand Down Expand Up @@ -181,7 +182,7 @@ export class MdSidenav implements AfterContentInit {
this.onCloseStart.emit();
}

if (this.focusTrapActive) {
if (!this.isFocusTrapDisabled) {
this._focusTrap.focusFirstTabbableElementWhenReady();
}

Expand Down

0 comments on commit b12a7c6

Please sign in to comment.