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', () => {
let scrollSpy: jasmine.Spy;
beforeEach(() => {
fixture.detectChanges();
page = setPage();
scrollSpy = spyOn(tocComponent, 'scrollToTop');
});
it('should have more than 4 displayed items', () => {
@ -149,7 +151,7 @@ describe('TocComponent', () => {
expect(aSecondary.classes.secondary).toEqual(true, 'has secondary class');
});
describe('after click expando button', () => {
describe('after click tocHeading button', () => {
beforeEach(() => {
page.tocHeadingButton.nativeElement.click();
@ -163,6 +165,66 @@ describe('TocComponent', () => {
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.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);
tocComponentDe = fixture.debugElement.children[0];
tocComponent = tocComponentDe.componentInstance;
tocService = TestBed.get(TocService);
fixture.detectChanges();
page = setPage();
});
@ -221,7 +285,6 @@ class TestTocService {
}
// tslint:disable:quotemark
function getTestTocList() {
return [
{

View File

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