feat(aio): scroll back to top when TOC more-items clicked to close

closes  #16482
Usability feature. When long embedded TOC, collapsing it should scroll user to TOC top, not leave in the middle of the page.
This commit is contained in:
Ward Bell 2017-05-06 22:16:54 -07:00 committed by Pete Bacon Darwin
parent cf7689ea7b
commit 98d83b2e2d
2 changed files with 75 additions and 5 deletions

View File

@ -111,10 +111,12 @@ describe('TocComponent', () => {
}); });
describe('when many TocItems', () => { describe('when many TocItems', () => {
let scrollSpy: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
fixture.detectChanges(); fixture.detectChanges();
page = setPage(); page = setPage();
scrollSpy = spyOn(tocComponent, 'scrollToTop');
}); });
it('should have more than 4 displayed items', () => { it('should have more than 4 displayed items', () => {
@ -149,7 +151,7 @@ describe('TocComponent', () => {
expect(aSecondary.classes.secondary).toEqual(true, 'has secondary class'); expect(aSecondary.classes.secondary).toEqual(true, 'has secondary class');
}); });
describe('after click expando button', () => { describe('after click tocHeading button', () => {
beforeEach(() => { beforeEach(() => {
page.tocHeadingButton.nativeElement.click(); page.tocHeadingButton.nativeElement.click();
@ -163,6 +165,66 @@ describe('TocComponent', () => {
it('should not have "closed" class', () => { it('should not have "closed" class', () => {
expect(tocComponentDe.children[0].classes.closed).toBeFalsy(); expect(tocComponentDe.children[0].classes.closed).toBeFalsy();
}); });
it('should not scroll', () => {
expect(scrollSpy).not.toHaveBeenCalled();
});
it('should be "closed" after clicking again', () => {
page.tocHeadingButton.nativeElement.click();
fixture.detectChanges();
expect(tocComponent.isClosed).toEqual(true);
});
it('should scroll after clicking again', () => {
page.tocHeadingButton.nativeElement.click();
fixture.detectChanges();
expect(scrollSpy).toHaveBeenCalled();
});
it('should be "closed" after clicking tocMoreButton', () => {
page.tocMoreButton.nativeElement.click();
fixture.detectChanges();
expect(tocComponent.isClosed).toEqual(true);
});
});
describe('after click tocMore button', () => {
beforeEach(() => {
page.tocMoreButton.nativeElement.click();
fixture.detectChanges();
});
it('should not be "closed"', () => {
expect(tocComponent.isClosed).toEqual(false);
});
it('should not have "closed" class', () => {
expect(tocComponentDe.children[0].classes.closed).toBeFalsy();
});
it('should not scroll', () => {
expect(scrollSpy).not.toHaveBeenCalled();
});
it('should be "closed" after clicking again', () => {
page.tocMoreButton.nativeElement.click();
fixture.detectChanges();
expect(tocComponent.isClosed).toEqual(true);
});
it('should scroll after clicking again', () => {
page.tocMoreButton.nativeElement.click();
fixture.detectChanges();
expect(scrollSpy).toHaveBeenCalled();
});
it('should be "closed" after clicking tocHeadingButton', () => {
page.tocHeadingButton.nativeElement.click();
fixture.detectChanges();
expect(tocComponent.isClosed).toEqual(true);
});
}); });
}); });
}); });
@ -174,6 +236,8 @@ describe('TocComponent', () => {
fixture = TestBed.createComponent(HostNotEmbeddedTocComponent); fixture = TestBed.createComponent(HostNotEmbeddedTocComponent);
tocComponentDe = fixture.debugElement.children[0]; tocComponentDe = fixture.debugElement.children[0];
tocComponent = tocComponentDe.componentInstance; tocComponent = tocComponentDe.componentInstance;
tocService = TestBed.get(TocService);
fixture.detectChanges(); fixture.detectChanges();
page = setPage(); page = setPage();
}); });
@ -221,7 +285,6 @@ class TestTocService {
} }
// tslint:disable:quotemark // tslint:disable:quotemark
function getTestTocList() { function getTestTocList() {
return [ return [
{ {

View File

@ -13,17 +13,18 @@ export class TocComponent implements OnInit, OnDestroy {
hasSecondary = false; hasSecondary = false;
hasToc = false; hasToc = false;
hostElement: HTMLElement;
isClosed = true; isClosed = true;
isEmbedded = false; isEmbedded = false;
private primaryMax = 4;
private onDestroy = new Subject(); private onDestroy = new Subject();
private primaryMax = 4;
tocList: TocItem[]; tocList: TocItem[];
constructor( constructor(
elementRef: ElementRef, elementRef: ElementRef,
private tocService: TocService) { private tocService: TocService) {
const hostElement = elementRef.nativeElement; this.hostElement = elementRef.nativeElement;
this.isEmbedded = hostElement.className.indexOf('embedded') !== -1; this.isEmbedded = this.hostElement.className.indexOf('embedded') !== -1;
} }
ngOnInit() { ngOnInit() {
@ -48,7 +49,13 @@ export class TocComponent implements OnInit, OnDestroy {
this.onDestroy.next(); this.onDestroy.next();
} }
scrollToTop() {
this.hostElement.parentElement.scrollIntoView();
if (window && window.scrollBy) { window.scrollBy(0, -100); }
}
toggle() { toggle() {
this.isClosed = !this.isClosed; this.isClosed = !this.isClosed;
if (this.isClosed) { this.scrollToTop(); }
} }
} }