Scroll element in to view using center and for all the scrollable ancestors

Closes #14527
This commit is contained in:
Cédric Krier
2026-01-20 18:43:53 +01:00
parent 26e171099d
commit faa9c7bf46
+50 -7
View File
@@ -79,16 +79,59 @@
};
Sao.common.scrollIntoViewIfNeeded = function(element) {
element = element[0];
if (element) {
var rect = element.getBoundingClientRect();
if (rect.bottom > window.innerHeight) {
element.scrollIntoView(false);
function isScrollable(el) {
let style = getComputedStyle(el);
return /(auto|scroll|overlay)/.test(
style.overflow + style.overflowY + style.overflowX
);
}
function getScrollableAncestors(el) {
let ancestors = [];
let parent = el.parentElement;
while (parent && parent !== document.body) {
if (isScrollable(parent)) {
ancestors.push(parent);
}
parent = parent.parentElement;
}
if (rect.top < 0) {
element.scrollIntoView();
ancestors.push(window);
return ancestors;
}
function scrollIntoViewWithin(el, container) {
let rect = el.getBoundingClientRect();
if (container === window) {
if (rect.top < 0 || rect.bottom > window.innerHeight) {
el.scrollIntoView({
block: 'center',
});
}
} else {
let container_rect = container.getBoundingClientRect();
let top_ = rect.top - container_rect.top;
let bottom = top_ + rect.height;
let target_top = container.scrollTop;
if (top_ < 0) {
target_top += top_ - container.clientHeight / 2;
} else if (bottom > container.clientHeight) {
target_top += bottom - container.clientHeight / 2
}
container.scrollTo({
top: Math.max(0, target_top),
});
}
}
element.each(function() {
let ancestors = getScrollableAncestors(this);
for (let ancestor of ancestors) {
scrollIntoViewWithin(this, ancestor);
}
});
};
// Handle click and Return press event