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:
parent
be998e830b
commit
b1d300dc26
|
@ -24,7 +24,7 @@ export class ScrollService implements OnDestroy {
|
||||||
poppedStateScrollPosition: ScrollPosition|null = null;
|
poppedStateScrollPosition: ScrollPosition|null = null;
|
||||||
// Whether the browser supports the necessary features for manual scroll restoration.
|
// Whether the browser supports the necessary features for manual scroll restoration.
|
||||||
supportManualScrollRestoration: boolean = !!window && ('scrollTo' in window) &&
|
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
|
// Offset from the top of the document to bottom of any static elements
|
||||||
// at the top (e.g. toolbar) + some margin
|
// at the top (e.g. toolbar) + some margin
|
||||||
|
|
|
@ -89,7 +89,7 @@ export class BrowserViewportScroller implements ViewportScroller {
|
||||||
*/
|
*/
|
||||||
getScrollPosition(): [number, number] {
|
getScrollPosition(): [number, number] {
|
||||||
if (this.supportsScrolling()) {
|
if (this.supportsScrolling()) {
|
||||||
return [this.window.scrollX, this.window.scrollY];
|
return [this.window.pageXOffset, this.window.pageYOffset];
|
||||||
} else {
|
} else {
|
||||||
return [0, 0];
|
return [0, 0];
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ export class BrowserViewportScroller implements ViewportScroller {
|
||||||
*/
|
*/
|
||||||
private supportScrollRestoration(): boolean {
|
private supportScrollRestoration(): boolean {
|
||||||
try {
|
try {
|
||||||
if (!this.window || !this.window.scrollTo) {
|
if (!this.supportsScrolling()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// The `scrollRestoration` property could be on the `history` instance or its prototype.
|
// The `scrollRestoration` property could be on the `history` instance or its prototype.
|
||||||
|
@ -166,7 +166,7 @@ export class BrowserViewportScroller implements ViewportScroller {
|
||||||
|
|
||||||
private supportsScrolling(): boolean {
|
private supportsScrolling(): boolean {
|
||||||
try {
|
try {
|
||||||
return !!this.window.scrollTo;
|
return !!this.window && !!this.window.scrollTo && 'pageXOffset' in this.window;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ describe('BrowserViewportScroller', () => {
|
||||||
let windowSpy: any;
|
let windowSpy: any;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
windowSpy = jasmine.createSpyObj('window', ['history', 'scrollTo']);
|
windowSpy =
|
||||||
|
jasmine.createSpyObj('window', ['history', 'scrollTo', 'pageXOffset', 'pageYOffset']);
|
||||||
windowSpy.history.scrollRestoration = 'auto';
|
windowSpy.history.scrollRestoration = 'auto';
|
||||||
documentSpy = jasmine.createSpyObj('document', ['getElementById', 'getElementsByName']);
|
documentSpy = jasmine.createSpyObj('document', ['getElementById', 'getElementsByName']);
|
||||||
scroller = new BrowserViewportScroller(documentSpy, windowSpy, null!);
|
scroller = new BrowserViewportScroller(documentSpy, windowSpy, null!);
|
||||||
|
|
|
@ -348,27 +348,24 @@ describe('bootstrap', () => {
|
||||||
await router.navigateByUrl('/aa');
|
await router.navigateByUrl('/aa');
|
||||||
window.scrollTo(0, 5000);
|
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');
|
await router.navigateByUrl('/fail');
|
||||||
expect(getScrollY()).toEqual(5000);
|
expect(window.pageYOffset).toEqual(5000);
|
||||||
|
|
||||||
await router.navigateByUrl('/bb');
|
await router.navigateByUrl('/bb');
|
||||||
window.scrollTo(0, 3000);
|
window.scrollTo(0, 3000);
|
||||||
|
|
||||||
expect(getScrollY()).toEqual(3000);
|
expect(window.pageYOffset).toEqual(3000);
|
||||||
|
|
||||||
await router.navigateByUrl('/cc');
|
await router.navigateByUrl('/cc');
|
||||||
expect(getScrollY()).toEqual(0);
|
expect(window.pageYOffset).toEqual(0);
|
||||||
|
|
||||||
await router.navigateByUrl('/aa#marker2');
|
await router.navigateByUrl('/aa#marker2');
|
||||||
expect(getScrollY()).toBeGreaterThanOrEqual(5900);
|
expect(window.pageYOffset).toBeGreaterThanOrEqual(5900);
|
||||||
expect(getScrollY()).toBeLessThan(6000); // offset
|
expect(window.pageYOffset).toBeLessThan(6000); // offset
|
||||||
|
|
||||||
await router.navigateByUrl('/aa#marker3');
|
await router.navigateByUrl('/aa#marker3');
|
||||||
expect(getScrollY()).toBeGreaterThanOrEqual(8900);
|
expect(window.pageYOffset).toBeGreaterThanOrEqual(8900);
|
||||||
expect(getScrollY()).toBeLessThan(9000);
|
expect(window.pageYOffset).toBeLessThan(9000);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue