luci-base: ui.js: improve mobile dropdown scroll behaviour
authorJo-Philipp Wich <jo@mein.io>
Wed, 25 Mar 2020 11:34:46 +0000 (12:34 +0100)
committerJo-Philipp Wich <jo@mein.io>
Thu, 7 May 2020 17:40:49 +0000 (19:40 +0200)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
(cherry picked from commit 0fb2f8f1d1d8748b56522cc81cf68d5aa04b9f50)

modules/luci-base/htdocs/luci-static/resources/ui.js

index dfc3dbdf02bbed03cdd452d57b1189fbc8598644..4a1895667f5ca478de450783a76bf494847d44d1 100644 (file)
@@ -1152,8 +1152,6 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                if ('ontouchstart' in window) {
                        var vpWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
                            vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
-                           scrollFrom = window.pageYOffset,
-                           scrollTo = scrollFrom + rect.top - vpHeight * 0.5,
                            start = null;
 
                        ul.style.top = sb.offsetHeight + 'px';
@@ -1162,6 +1160,31 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                        ul.style.maxHeight = (vpHeight * 0.5) + 'px';
                        ul.style.WebkitOverflowScrolling = 'touch';
 
+                       function getScrollParent(element) {
+                               var parent = element,
+                                   style = getComputedStyle(element),
+                                   excludeStaticParent = (style.position === 'absolute');
+
+                               if (style.position === 'fixed')
+                                       return document.body;
+
+                               while ((parent = parent.parentElement) != null) {
+                                       style = getComputedStyle(parent);
+
+                                       if (excludeStaticParent && style.position === 'static')
+                                               continue;
+
+                                       if (/(auto|scroll)/.test(style.overflow + style.overflowY + style.overflowX))
+                                               return parent;
+                               }
+
+                               return document.body;
+                       }
+
+                       var scrollParent = getScrollParent(sb),
+                           scrollFrom = scrollParent.scrollTop,
+                           scrollTo = scrollFrom + rect.top - vpHeight * 0.5;
+
                        var scrollStep = function(timestamp) {
                                if (!start) {
                                        start = timestamp;
@@ -1170,11 +1193,11 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
 
                                var duration = Math.max(timestamp - start, 1);
                                if (duration < 100) {
-                                       document.body.scrollTop = scrollFrom + (scrollTo - scrollFrom) * (duration / 100);
+                                       scrollParent.scrollTop = scrollFrom + (scrollTo - scrollFrom) * (duration / 100);
                                        window.requestAnimationFrame(scrollStep);
                                }
                                else {
-                                       document.body.scrollTop = scrollTo;
+                                       scrollParent.scrollTop = scrollTo;
                                }
                        };