Break out scrollIntoViewIfNeeded into freely usable function

This commit is contained in:
Aarni Koskela 2021-12-09 11:22:08 +02:00
parent 3d11a80c9c
commit 86cef81e9c

View File

@ -26,11 +26,11 @@ export function html2Str(html: string): string {
// scrollIntoViewIfNeeded polyfill // scrollIntoViewIfNeeded polyfill
if (typeof Element !== 'undefined' && !(Element as any).prototype.scrollIntoViewIfNeeded) { export function scrollIntoViewIfNeeded(el: HTMLElement, centerIfNeeded = true) {
(Element as any).prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { const parent = el.parentNode as HTMLElement | null;
centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; if (!parent) {
return;
const parent = this.parentNode; }
const parentComputedStyle = window.getComputedStyle(parent, undefined); const parentComputedStyle = window.getComputedStyle(parent, undefined);
const parentBorderTopWidth = parseInt( const parentBorderTopWidth = parseInt(
parentComputedStyle.getPropertyValue('border-top-width'), parentComputedStyle.getPropertyValue('border-top-width'),
@ -40,36 +40,41 @@ if (typeof Element !== 'undefined' && !(Element as any).prototype.scrollIntoView
parentComputedStyle.getPropertyValue('border-left-width'), parentComputedStyle.getPropertyValue('border-left-width'),
10, 10,
); );
const overTop = this.offsetTop - parent.offsetTop < parent.scrollTop; const overTop = el.offsetTop - parent.offsetTop < parent.scrollTop;
const overBottom = const overBottom =
this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth > el.offsetTop - parent.offsetTop + el.clientHeight - parentBorderTopWidth >
parent.scrollTop + parent.clientHeight; parent.scrollTop + parent.clientHeight;
const overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft; const overLeft = el.offsetLeft - parent.offsetLeft < parent.scrollLeft;
const overRight = const overRight =
this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth > el.offsetLeft - parent.offsetLeft + el.clientWidth - parentBorderLeftWidth >
parent.scrollLeft + parent.clientWidth; parent.scrollLeft + parent.clientWidth;
const alignWithTop = overTop && !overBottom; const alignWithTop = overTop && !overBottom;
if ((overTop || overBottom) && centerIfNeeded) { if ((overTop || overBottom) && centerIfNeeded) {
parent.scrollTop = parent.scrollTop =
this.offsetTop - el.offsetTop -
parent.offsetTop - parent.offsetTop -
parent.clientHeight / 2 - parent.clientHeight / 2 -
parentBorderTopWidth + parentBorderTopWidth +
this.clientHeight / 2; el.clientHeight / 2;
} }
if ((overLeft || overRight) && centerIfNeeded) { if ((overLeft || overRight) && centerIfNeeded) {
parent.scrollLeft = parent.scrollLeft =
this.offsetLeft - el.offsetLeft -
parent.offsetLeft - parent.offsetLeft -
parent.clientWidth / 2 - parent.clientWidth / 2 -
parentBorderLeftWidth + parentBorderLeftWidth +
this.clientWidth / 2; el.clientWidth / 2;
} }
if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) { if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
this.scrollIntoView(alignWithTop); el.scrollIntoView(alignWithTop);
} }
}
if (typeof Element !== 'undefined' && !(Element as any).prototype.scrollIntoViewIfNeeded) {
(Element as any).prototype.scrollIntoViewIfNeeded = function (centerIfNeeded = true) {
scrollIntoViewIfNeeded(this, centerIfNeeded);
}; };
} }