diff --git a/aio/src/app/app.component.spec.ts b/aio/src/app/app.component.spec.ts index ebeaba3273..94e29dbedb 100644 --- a/aio/src/app/app.component.spec.ts +++ b/aio/src/app/app.component.spec.ts @@ -286,14 +286,14 @@ describe('AppComponent', () => { const scrollService: AutoScrollService = fixture.debugElement.injector.get(AutoScrollService); spyOn(scrollService, 'scroll'); locationService.go('some/url#fragment'); - expect(scrollService.scroll).toHaveBeenCalledWith(jasmine.any(HTMLElement)); + expect(scrollService.scroll).toHaveBeenCalledWith(); }); it('should be called when a document has been rendered', () => { const scrollService: AutoScrollService = fixture.debugElement.injector.get(AutoScrollService); spyOn(scrollService, 'scroll'); component.onDocRendered(); - expect(scrollService.scroll).toHaveBeenCalledWith(jasmine.any(HTMLElement)); + expect(scrollService.scroll).toHaveBeenCalledWith(); }); }); diff --git a/aio/src/app/app.component.ts b/aio/src/app/app.component.ts index 88db3bf41c..f3c263c8e6 100644 --- a/aio/src/app/app.component.ts +++ b/aio/src/app/app.component.ts @@ -106,7 +106,7 @@ export class AppComponent implements OnInit { // Scroll to the anchor in the hash fragment. autoScroll() { - this.autoScrollService.scroll(this.docViewer.nativeElement.offsetParent); + this.autoScrollService.scroll(); } onDocRendered() { diff --git a/aio/src/app/shared/auto-scroll.service.spec.ts b/aio/src/app/shared/auto-scroll.service.spec.ts index 6fb5309241..9e226afffc 100644 --- a/aio/src/app/shared/auto-scroll.service.spec.ts +++ b/aio/src/app/shared/auto-scroll.service.spec.ts @@ -3,11 +3,9 @@ import { PlatformLocation } from '@angular/common'; import { DOCUMENT } from '@angular/platform-browser'; import { AutoScrollService } from './auto-scroll.service'; - describe('AutoScrollService', () => { let injector: ReflectiveInjector, autoScroll: AutoScrollService, - container: HTMLElement, location: MockPlatformLocation, document: MockDocument; @@ -16,6 +14,7 @@ describe('AutoScrollService', () => { } class MockDocument { + body = new MockElement(); getElementById = jasmine.createSpy('Document getElementById'); } @@ -23,6 +22,10 @@ describe('AutoScrollService', () => { scrollIntoView = jasmine.createSpy('Element scrollIntoView'); } + beforeEach(() => { + spyOn(window, 'scrollBy'); + }); + beforeEach(() => { injector = ReflectiveInjector.resolveAndCreate([ AutoScrollService, @@ -31,34 +34,37 @@ describe('AutoScrollService', () => { ]); location = injector.get(PlatformLocation); document = injector.get(DOCUMENT); - container = window.document.createElement('div'); - container.scrollTop = 100; autoScroll = injector.get(AutoScrollService); }); - it('should scroll the container to the top if there is no hash', () => { + it('should scroll to the top if there is no hash', () => { location.hash = ''; - autoScroll.scroll(container); - expect(container.scrollTop).toEqual(0); + const topOfPage = new MockElement(); + document.getElementById.and + .callFake(id => id === 'top-of-page' ? topOfPage : null); + + autoScroll.scroll(); + expect(topOfPage.scrollIntoView).toHaveBeenCalled(); }); - it('should scroll the container to the top if the hash does not match an element id', () => { - location.hash = 'some-id'; + it('should not scroll if the hash does not match an element id', () => { + location.hash = 'not-found'; document.getElementById.and.returnValue(null); - autoScroll.scroll(container); - expect(document.getElementById).toHaveBeenCalledWith('some-id'); - expect(container.scrollTop).toEqual(0); + autoScroll.scroll(); + expect(document.getElementById).toHaveBeenCalledWith('not-found'); + expect(window.scrollBy).not.toHaveBeenCalled(); }); - it('should scroll the container to the element whose id matches the hash', () => { + it('should scroll to the element whose id matches the hash', () => { const element = new MockElement(); location.hash = 'some-id'; document.getElementById.and.returnValue(element); - autoScroll.scroll(container); + autoScroll.scroll(); expect(document.getElementById).toHaveBeenCalledWith('some-id'); expect(element.scrollIntoView).toHaveBeenCalled(); + expect(window.scrollBy).toHaveBeenCalledWith(0, -80); }); }); diff --git a/aio/src/app/shared/auto-scroll.service.ts b/aio/src/app/shared/auto-scroll.service.ts index e99efb6375..6e36ab084a 100644 --- a/aio/src/app/shared/auto-scroll.service.ts +++ b/aio/src/app/shared/auto-scroll.service.ts @@ -7,22 +7,23 @@ import { DOCUMENT } from '@angular/platform-browser'; */ @Injectable() export class AutoScrollService { - constructor( @Inject(DOCUMENT) private document: any, private location: PlatformLocation) { } /** - * Scroll the contents of the container - * to the element with id extracted from the current location hash fragment + * Scroll to the element with id extracted from the current location hash fragment + * Scroll to top if no hash + * Don't scroll if hash not found */ - scroll(container: HTMLElement) { + scroll() { const hash = this.getCurrentHash(); - const element: HTMLElement = this.document.getElementById(hash); + const element: HTMLElement = hash + ? this.document.getElementById(hash) + : this.document.getElementById('top-of-page') || this.document.body; if (element) { element.scrollIntoView(); - } else { - container.scrollTop = 0; + if (window && window.scrollBy) { window.scrollBy(0, -80); } } }