diff options
author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-01-11 14:21:10 -0500 |
---|---|---|
committer | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-01-22 20:38:21 -0500 |
commit | d59f2022b9582a9a310c8a93eb3b4e0bbab097a5 (patch) | |
tree | 8d3e58d1cc36a97fde947d1265dcf2b9876c4fd1 /ext/fg/js/popup.js | |
parent | 21dbb19565d2a0b024d3240d93a961c989504bcb (diff) |
Allow viewport to be used for constraining popup position
Diffstat (limited to 'ext/fg/js/popup.js')
-rw-r--r-- | ext/fg/js/popup.js | 114 |
1 files changed, 75 insertions, 39 deletions
diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 6c98491b..710d95cd 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -258,6 +258,7 @@ class Popup { Popup._getPositionForVerticalText ); + const viewport = Popup._getViewport(optionsGeneral.popupScaleRelativeToVisualViewport); const scale = this._contentScale; const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale; this._containerSizeContentScale = scale; @@ -265,8 +266,7 @@ class Popup { elementRect, Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale), Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale), - document.body.clientWidth, - window.innerHeight, + viewport, scale, optionsGeneral, writingMode @@ -353,49 +353,49 @@ class Popup { } } - static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral) { - let x = elementRect.left + optionsGeneral.popupHorizontalOffset * offsetScale; - const overflowX = Math.max(x + width - maxWidth, 0); - if (overflowX > 0) { - if (x >= overflowX) { - x -= overflowX; - } else { - width = maxWidth; - x = 0; - } - } - + static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) { const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); - + const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale; const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale; - const [y, h, below] = Popup._limitGeometry( + + const [x, w] = Popup._getConstrainedPosition( + elementRect.right - horizontalOffset, + elementRect.left + horizontalOffset, + width, + viewport.left, + viewport.right, + true + ); + const [y, h, below] = Popup._getConstrainedPositionBinary( elementRect.top - verticalOffset, elementRect.bottom + verticalOffset, height, - maxHeight, + viewport.top, + viewport.bottom, preferBelow ); - - return [x, y, width, h, below]; + return [x, y, w, h, below]; } - static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral, writingMode) { + static _getPositionForVerticalText(elementRect, width, height, viewport, offsetScale, optionsGeneral, writingMode) { const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode); const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale; const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale; - const [x, w] = Popup._limitGeometry( + const [x, w] = Popup._getConstrainedPositionBinary( elementRect.left - horizontalOffset, elementRect.right + horizontalOffset, width, - maxWidth, + viewport.left, + viewport.right, preferRight ); - const [y, h, below] = Popup._limitGeometry( + const [y, h, below] = Popup._getConstrainedPosition( elementRect.bottom - verticalOffset, elementRect.top + verticalOffset, height, - maxHeight, + viewport.top, + viewport.bottom, true ); return [x, y, w, h, below]; @@ -424,23 +424,36 @@ class Popup { } } - static _limitGeometry(positionBefore, positionAfter, size, limit, preferAfter) { - let after = preferAfter; - let position = 0; - const overflowBefore = Math.max(0, size - positionBefore); - const overflowAfter = Math.max(0, positionAfter + size - limit); + static _getConstrainedPosition(positionBefore, positionAfter, size, minLimit, maxLimit, after) { + size = Math.min(size, maxLimit - minLimit); + + let position; + if (after) { + position = Math.max(minLimit, positionAfter); + position = position - Math.max(0, (position + size) - maxLimit); + } else { + position = Math.min(maxLimit, positionBefore) - size; + position = position + Math.max(0, minLimit - position); + } + + return [position, size, after]; + } + + static _getConstrainedPositionBinary(positionBefore, positionAfter, size, minLimit, maxLimit, after) { + const overflowBefore = minLimit - (positionBefore - size); + const overflowAfter = (positionAfter + size) - maxLimit; + if (overflowAfter > 0 || overflowBefore > 0) { - if (overflowAfter < overflowBefore) { - size = Math.max(0, size - overflowAfter); - position = positionAfter; - after = true; - } else { - size = Math.max(0, size - overflowBefore); - position = Math.max(0, positionBefore - size); - after = false; - } + after = (overflowAfter < overflowBefore); + } + + let position; + if (after) { + size -= Math.max(0, overflowAfter); + position = Math.max(minLimit, positionAfter); } else { - position = preferAfter ? positionAfter : positionBefore - size; + size -= Math.max(0, overflowBefore); + position = Math.min(maxLimit, positionBefore) - size; } return [position, size, after]; @@ -479,6 +492,29 @@ class Popup { // NOP } } + + static _getViewport(useVisualViewport) { + if (useVisualViewport) { + const visualViewport = window.visualViewport; + if (visualViewport !== null && typeof visualViewport === 'object') { + const left = visualViewport.offsetLeft; + const top = visualViewport.offsetTop; + return { + left, + top, + right: left + visualViewport.width, + bottom: top + visualViewport.height + }; + } + } + + return { + left: 0, + top: 0, + right: document.body.clientWidth, + bottom: window.innerHeight + }; + } } Popup.outerStylesheet = null; |