Skip to content

Commit

Permalink
fix(common): Prefer to use pageXOffset / pageYOffset instance of scro…
Browse files Browse the repository at this point in the history
…llX / scrollY (#28262)

This fix ensures a better cross-browser compatibility.
This fix has been used for angular.io.

PR Close #28262
  • Loading branch information
wKoza authored and AndrewKushnir committed Nov 19, 2020
1 parent be998e8 commit b1d300d
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 15 deletions.
2 changes: 1 addition & 1 deletion aio/src/app/shared/scroll.service.ts
Expand Up @@ -24,7 +24,7 @@ export class ScrollService implements OnDestroy {
poppedStateScrollPosition: ScrollPosition|null = null;
// Whether the browser supports the necessary features for manual scroll restoration.
supportManualScrollRestoration: boolean = !!window && ('scrollTo' in window) &&
('scrollX' in window) && ('scrollY' in window) && isScrollRestorationWritable();
('pageXOffset' in window) && isScrollRestorationWritable();

// Offset from the top of the document to bottom of any static elements
// at the top (e.g. toolbar) + some margin
Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/viewport_scroller.ts
Expand Up @@ -89,7 +89,7 @@ export class BrowserViewportScroller implements ViewportScroller {
*/
getScrollPosition(): [number, number] {
if (this.supportsScrolling()) {
return [this.window.scrollX, this.window.scrollY];
return [this.window.pageXOffset, this.window.pageYOffset];
} else {
return [0, 0];
}
Expand Down Expand Up @@ -149,7 +149,7 @@ export class BrowserViewportScroller implements ViewportScroller {
*/
private supportScrollRestoration(): boolean {
try {
if (!this.window || !this.window.scrollTo) {
if (!this.supportsScrolling()) {
return false;
}
// The `scrollRestoration` property could be on the `history` instance or its prototype.
Expand All @@ -166,7 +166,7 @@ export class BrowserViewportScroller implements ViewportScroller {

private supportsScrolling(): boolean {
try {
return !!this.window.scrollTo;
return !!this.window && !!this.window.scrollTo && 'pageXOffset' in this.window;
} catch {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/common/test/viewport_scroller_spec.ts
Expand Up @@ -15,7 +15,8 @@ describe('BrowserViewportScroller', () => {
let windowSpy: any;

beforeEach(() => {
windowSpy = jasmine.createSpyObj('window', ['history', 'scrollTo']);
windowSpy =
jasmine.createSpyObj('window', ['history', 'scrollTo', 'pageXOffset', 'pageYOffset']);
windowSpy.history.scrollRestoration = 'auto';
documentSpy = jasmine.createSpyObj('document', ['getElementById', 'getElementsByName']);
scroller = new BrowserViewportScroller(documentSpy, windowSpy, null!);
Expand Down
17 changes: 7 additions & 10 deletions packages/router/test/bootstrap.spec.ts
Expand Up @@ -348,27 +348,24 @@ describe('bootstrap', () => {
await router.navigateByUrl('/aa');
window.scrollTo(0, 5000);

// IE 11 uses non-standard pageYOffset instead of scrollY
const getScrollY = () => window.scrollY !== undefined ? window.scrollY : window.pageYOffset;

await router.navigateByUrl('/fail');
expect(getScrollY()).toEqual(5000);
expect(window.pageYOffset).toEqual(5000);

await router.navigateByUrl('/bb');
window.scrollTo(0, 3000);

expect(getScrollY()).toEqual(3000);
expect(window.pageYOffset).toEqual(3000);

await router.navigateByUrl('/cc');
expect(getScrollY()).toEqual(0);
expect(window.pageYOffset).toEqual(0);

await router.navigateByUrl('/aa#marker2');
expect(getScrollY()).toBeGreaterThanOrEqual(5900);
expect(getScrollY()).toBeLessThan(6000); // offset
expect(window.pageYOffset).toBeGreaterThanOrEqual(5900);
expect(window.pageYOffset).toBeLessThan(6000); // offset

await router.navigateByUrl('/aa#marker3');
expect(getScrollY()).toBeGreaterThanOrEqual(8900);
expect(getScrollY()).toBeLessThan(9000);
expect(window.pageYOffset).toBeGreaterThanOrEqual(8900);
expect(window.pageYOffset).toBeLessThan(9000);
done();
});

Expand Down

0 comments on commit b1d300d

Please sign in to comment.