From 0fb2f8f1d1d8748b56522cc81cf68d5aa04b9f50 Mon Sep 17 00:00:00 2001
From: Jo-Philipp Wich <jo@mein.io>
Date: Wed, 25 Mar 2020 12:34:46 +0100
Subject: [PATCH] luci-base: ui.js: improve mobile dropdown scroll behaviour

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
---
 .../htdocs/luci-static/resources/ui.js        | 31 ++++++++++++++++---
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js
index 0e196df4b..906500eaa 100644
--- a/modules/luci-base/htdocs/luci-static/resources/ui.js
+++ b/modules/luci-base/htdocs/luci-static/resources/ui.js
@@ -619,8 +619,6 @@ var UIDropdown = UIElement.extend({
 		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';
@@ -629,6 +627,31 @@ var UIDropdown = UIElement.extend({
 			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;
@@ -637,11 +660,11 @@ var UIDropdown = UIElement.extend({
 
 				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;
 				}
 			};
 
-- 
2.25.1