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

Reply via email to