luci-base: ui.js: determine dropdown position relative to overflow parent
authorJo-Philipp Wich <jo@mein.io>
Wed, 9 Jun 2021 19:45:13 +0000 (21:45 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 9 Jun 2021 19:55:43 +0000 (21:55 +0200)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/htdocs/luci-static/resources/ui.js

index 5a0e6d297b748b992792fcb4493bcb9e732bdb97..0e909b6dcc717dbfd76d25930f1b69300f3a976a 100644 (file)
@@ -1201,6 +1201,28 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                return sb;
        },
 
+       /** @private */
+       getScrollParent: function(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;
+       },
+
        /** @private */
        openDropdown: function(sb) {
                var st = window.getComputedStyle(sb, null),
@@ -1209,7 +1231,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                    fl = findParent(sb, '.cbi-value-field'),
                    sel = ul.querySelector('[selected]'),
                    rect = sb.getBoundingClientRect(),
-                   items = Math.min(this.options.dropdown_items, li.length);
+                   items = Math.min(this.options.dropdown_items, li.length),
+                   scrollParent = this.getScrollParent(sb);
 
                document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) {
                        s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {}));
@@ -1234,29 +1257,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                        ul.style.maxHeight = (vpHeight * 0.5) + 'px';
                        ul.style.WebkitOverflowScrolling = 'touch';
 
-                       var getScrollParent = function(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,
+                       var scrollFrom = scrollParent.scrollTop,
                            scrollTo = scrollFrom + rect.top - vpHeight * 0.5;
 
                        var scrollStep = function(timestamp) {
@@ -1282,10 +1283,11 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
                        ul.style.top = ul.style.bottom = '';
 
                        window.requestAnimationFrame(function() {
-                               var itemHeight = li[Math.max(0, li.length - 2)].getBoundingClientRect().height,
+                               var containerRect = scrollParent.getBoundingClientRect(),
+                                   itemHeight = li[Math.max(0, li.length - 2)].getBoundingClientRect().height,
                                    fullHeight = 0,
-                                   spaceAbove = rect.top,
-                                   spaceBelow = window.innerHeight - rect.height - rect.top;
+                                   spaceAbove = rect.top - containerRect.top,
+                                   spaceBelow = containerRect.bottom - rect.bottom;
 
                                for (var i = 0; i < (items == -1 ? li.length : items); i++)
                                        fullHeight += li[i].getBoundingClientRect().height;