details: https://code.tryton.org/tryton/commit/255081359322
branch: 7.8
user: Cédric Krier <[email protected]>
date: Tue Jan 20 18:43:53 2026 +0100
description:
Scroll element in to view using center and for all the scrollable
ancestors
Closes #14527
(grafted from accca4565e9092605e19afdb22d1bed33d1edab2)
diffstat:
sao/src/common.js | 57 ++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 50 insertions(+), 7 deletions(-)
diffs (70 lines):
diff -r 3e6bf6105c91 -r 255081359322 sao/src/common.js
--- a/sao/src/common.js Sun Jan 18 13:38:12 2026 +0100
+++ b/sao/src/common.js Tue Jan 20 18:43:53 2026 +0100
@@ -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