summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-01-11 14:21:10 -0500
committertoasted-nutbread <toasted-nutbread@users.noreply.github.com>2020-01-22 20:38:21 -0500
commitd59f2022b9582a9a310c8a93eb3b4e0bbab097a5 (patch)
tree8d3e58d1cc36a97fde947d1265dcf2b9876c4fd1
parent21dbb19565d2a0b024d3240d93a961c989504bcb (diff)
Allow viewport to be used for constraining popup position
-rw-r--r--ext/fg/js/popup.js114
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;