fix(common): Prefer to use pageXOffset / pageYOffset instance of scrollX / scrollY (#28262)

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

PR Close #28262
This commit is contained in:
WilliamKoza 2019-01-20 14:12:52 +01:00 committed by Andrew Kushnir
parent be998e830b
commit b1d300dc26
4 changed files with 13 additions and 15 deletions

View File

@ -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

View File

@ -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];
}
@ -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.
@ -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;
}

View File

@ -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!);

View File

@ -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();
});