Confirmed Sticky form submit rows are incorrectly positioned inside scrollable overlays

Painbaker

Well-known member
Licensed customer
Affected version
2.3.13
Sticky form submit rows are incorrectly positioned inside scrollable overlays because FormSubmitRow only listens to window scrolling

Suggested fix:

Detect the closest .overlay-container listen to its scroll event and include its scrollTop when calculating the fixed row position

Diff:
diff --git a/js/xf/form.js b/js/xf/form.js
--- a/js/xf/form.js
+++ b/js/xf/form.js
@@ -1686,6 +1686,7 @@
 		winHeight: 0,
 		containerTop: 0,
 		containerBorderLeftWidth: 0,
+		overlayContainer: null,
 		topOffset: 0,
 		elBottom: 0,
 		state: 'normal',
@@ -1708,6 +1709,7 @@
 			}
 
 			this.container = container
+			this.overlayContainer = container.closest('.overlay-container')
 
 			this.topOffset = this.options.topOffset
 			this.fixEl = target.querySelector(this.options.fixedChild)
@@ -1723,6 +1725,11 @@
 				XF.on(fixedParent, 'scroll', this.onScroll.bind(this))
 			}
 
+			if (this.overlayContainer)
+			{
+				XF.on(this.overlayContainer, 'scroll', this.onScroll.bind(this))
+			}
+
 			XF.on(document.body, 'xf:layout', this.recalcAndUpdate.bind(this))
 
 			setTimeout(this.recalcAndUpdate.bind(this), 250)
@@ -1790,10 +1797,33 @@
 			let containerOffset,
 				bottomFixHeight = XF.NoticeWatcher.getBottomFixerNoticeHeight() || 0
 
-			let isOverlay = this.container.closest('.overlay')
-			if (isOverlay)
+			const overlay = this.container.closest('.overlay')
+			if (overlay)
 			{
-				bottomFixHeight = 0
+				const targetRect = this.target.getBoundingClientRect()
+				if (targetRect.bottom <= winHeight)
+				{
+					if (this.state != 'normal')
+					{
+						this.resetTarget()
+						this.state = 'normal'
+					}
+
+					return
+				}
+
+				const containerRect = this.container.getBoundingClientRect()
+
+				this.fixEl.style.position = 'fixed'
+				this.fixEl.style.top = `${ winHeight - this.fixElHeight + this.overlayContainer.scrollTop }px`
+				this.fixEl.style.right = 'auto'
+				this.fixEl.style.bottom = 'auto'
+				this.fixEl.style.left = `${ containerRect.left + this.containerBorderLeftWidth }px`
+				this.fixEl.style.width = `${ this.container.clientWidth }px`
+
+				this.setTargetSticky(true)
+				this.state = 'stuck'
+				return
 			}
 
 			let screenBottom = this.getScrollTop() + winHeight - bottomFixHeight
 
Last edited:
Back
Top Bottom