luci-base: ui.js: determine dropdown position relative to overflow parent

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2021-06-09 21:45:13 +02:00
parent fb82e03635
commit e3bf521edb

View 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;