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