Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Popover position2 #7908

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 46 additions & 4 deletions packages/main/src/Popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import PopoverTemplate from "./generated/templates/PopoverTemplate.lit.js";
import browserScrollbarCSS from "./generated/themes/BrowserScrollbar.css.js";
import PopupsCommonCss from "./generated/themes/PopupsCommon.css.js";
import PopoverCss from "./generated/themes/Popover.css.js";
import { calculateOrigCoordinates } from "./PopoverHelpers.js";

const scale = 0.7;

const ARROW_SIZE = 8;

Expand Down Expand Up @@ -443,7 +446,7 @@ class Popover extends Popup {
let left = clamp(
this._left!,
Popover.VIEWPORT_MARGIN,
document.documentElement.clientWidth - popoverSize.width - Popover.VIEWPORT_MARGIN,
document.documentElement.clientWidth * scale - popoverSize.width - Popover.VIEWPORT_MARGIN,
);

if (this.actualPlacementType === PopoverPlacementType.Right) {
Expand All @@ -453,7 +456,7 @@ class Popover extends Popup {
let top = clamp(
this._top!,
Popover.VIEWPORT_MARGIN,
document.documentElement.clientHeight - popoverSize.height - Popover.VIEWPORT_MARGIN,
document.documentElement.clientHeight * scale - popoverSize.height - Popover.VIEWPORT_MARGIN,
);

if (this.actualPlacementType === PopoverPlacementType.Bottom) {
Expand All @@ -463,7 +466,19 @@ class Popover extends Popup {
this.arrowTranslateX = placement!.arrow.x;
this.arrowTranslateY = placement!.arrow.y;

const transformedParent = this.findTransformedParent();
top = this._adjustForIOSKeyboard(top);
const stackingContextOffset = this._getStackingContextOffset();
const { x: stackingLeft, y: stackingTop } = calculateOrigCoordinates(stackingContextOffset.left, stackingContextOffset.top, transformedParent);
left -= stackingLeft;
top -= stackingTop;

// containingNode
if (transformedParent) {
const { x, y } = calculateOrigCoordinates(left, top, transformedParent);
left = x;
top = y;
}

Object.assign(this.style, {
top: `${top}px`,
Expand All @@ -475,6 +490,16 @@ class Popover extends Popup {
}
}

findTransformedParent() {
let parent = this.parentElement;
while (parent) {
if (window.getComputedStyle(parent).transform) {
return parent;
}
parent = parent.parentElement;
}
}

/**
* Adjust the desired top position to compensate for shift of the screen
* caused by opened keyboard on iOS which affects all elements with position:fixed.
Expand All @@ -492,6 +517,23 @@ class Popover extends Popup {
return top + (Number.parseInt(this.style.top || "0") - actualTop);
}

_getStackingContextOffset() {
let parentNode = this.parentElement ? this.parentNode as HTMLElement : (this.parentNode as ShadowRoot).host as HTMLElement;

while (parentNode) {
const computedStyle = getComputedStyle(parentNode);

if (["size", "inline-size"].indexOf(computedStyle.containerType) > -1
|| computedStyle.transform !== "none") {
return parentNode.getBoundingClientRect();
}

parentNode = parentNode.parentElement ? parentNode.parentNode as HTMLElement : (parentNode.parentNode as ShadowRoot).host as HTMLElement;
}

return { left: 0, top: 0 };
}

getPopoverSize(): PopoverSize {
const rect = this.getBoundingClientRect(),
width = rect.width,
Expand Down Expand Up @@ -520,8 +562,8 @@ class Popover extends Popup {
let top = 0;
const allowTargetOverlap = this.allowTargetOverlap;

const clientWidth = document.documentElement.clientWidth;
const clientHeight = document.documentElement.clientHeight;
const clientWidth = document.documentElement.clientWidth * scale;
const clientHeight = document.documentElement.clientHeight * scale;

let maxHeight = clientHeight;
let maxWidth = clientWidth;
Expand Down
39 changes: 39 additions & 0 deletions packages/main/src/PopoverHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @ts-nocheck
const applyMatrix = (a: number, b: number, c: number, d: number, e: number, f: number, x: number, y: number): { x: number, y: number } => {
return { x: a*x + c*y + e, y: b*x + d*y + f}

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

A space is required before '}'

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Missing semicolon

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

A space is required before '}'

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Missing semicolon

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

A space is required before '}'

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Missing semicolon

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

A space is required before '}'

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Missing semicolon

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Operator '*' must be spaced

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

A space is required before '}'

Check failure on line 3 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Missing semicolon
}

Check failure on line 4 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

Missing semicolon

Check failure on line 4 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

Missing semicolon

Check failure on line 4 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

Missing semicolon

Check failure on line 4 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

Missing semicolon

Check failure on line 4 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

Missing semicolon

function translate(x: number, y: number, tx: number, ty: number) {
return applyMatrix(1,0,0,1,tx,ty,x,y);

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (base)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-1)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (fiori)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

A space is required after ','

Check failure on line 7 in packages/main/src/PopoverHelpers.ts

View workflow job for this annotation

GitHub Actions / check (main:suite-2)

A space is required after ','
}
function scale(x: number, y: number, scaleX: number, scaleY: number) {
return applyMatrix(scaleX, 0, 0, scaleY, 0, 0, x, y);
}

// let translated = translate(8, 8, -466, -26)
// let scaled = scale(translated.x, translated.y, 0.7, 0.7)
// let translated2 = translate(scaled.x, scaled.y, 466, 26)

function scaleWithOrigin(x: number, y: number, scaleX: number, scaleY: number, originX: number, originY: number) {
let translated = translate(x, y, -1 * originX, -1 * originY)
let scaled = scale(translated.x, translated.y, scaleX, scaleY)
let translated2 = translate(scaled.x, scaled.y, originX, originY)
return translated2;
}

const calculateOrigCoordinates = (x: number, y: number, transformedElement: HTMLElement | undefined) => {
if (!transformedElement) {
return { x, y };
}
let { transform, transformOrigin, marginLeft, marginTop } = window.getComputedStyle(transformedElement);
const transformArgs = transform.replace("matrix(", "").replace(")", "").split(",").map(v => parseFloat(v));

marginLeft = parseFloat(marginLeft);
marginTop = parseFloat(marginTop);

const [ originX, originY ] = transformOrigin.split(" ").map(x => parseFloat(x));
return scaleWithOrigin(x, y, 1 / transformArgs[0], 1 / transformArgs[3], originX + (marginLeft as number), originY + (marginTop as number));
}

window.calculateOrigCoordinates = calculateOrigCoordinates;
export { scaleWithOrigin, calculateOrigCoordinates };
57 changes: 34 additions & 23 deletions packages/main/test/pages/Popover.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,37 @@
<body class="popover2auto">
<iframe id="clickThisIframe" src="//localhost:8080"></iframe>

<ui5-tabcontainer>
<ui5-tab text="tab 1">
<ui5-button id="popbtn">Open Popover</ui5-button>

<ui5-popover placement-type="Bottom" hide-arrow id="danger">

<ui5-list>
<ui5-li>Hello</ui5-li>
<ui5-li>World</ui5-li>
<ui5-li>Again</ui5-li>
</ui5-list>

<br>
<br>

<ui5-button id="bigDanger">Super Danger !</ui5-button>

<ui5-popover id="bigDangerPop">
<ui5-list>
<ui5-li>Hello</ui5-li>
<ui5-li>World</ui5-li>
<ui5-li>Again</ui5-li>
</ui5-list>
</ui5-popover>
</ui5-popover>
</ui5-tab>
<ui5-tab text="tab 2">

</ui5-tab>
</ui5-tabcontainer>

<ui5-button id="btn">Click me !</ui5-button>

<ui5-popover id="pop" class="popover6auto" placement-type="Top" accessible-name="This popover is important">
Expand All @@ -43,29 +74,9 @@
<br>
<br>

<ui5-button id="popbtn">Open Popover</ui5-button>

<ui5-popover placement-type="Bottom" hide-arrow id="danger">

<ui5-list>
<ui5-li>Hello</ui5-li>
<ui5-li>World</ui5-li>
<ui5-li>Again</ui5-li>
</ui5-list>

<br>
<br>

<ui5-button id="bigDanger">Super Danger !</ui5-button>

<ui5-popover id="bigDangerPop">
<ui5-list>
<ui5-li>Hello</ui5-li>
<ui5-li>World</ui5-li>
<ui5-li>Again</ui5-li>
</ui5-list>
</ui5-popover>
</ui5-popover>

<br>
<br>
Expand Down Expand Up @@ -395,7 +406,7 @@
<ui5-button id="popoverFocusButton">Dialog Focus</ui5-button>
<ui5-popover id="popoverFocus">
<div slot="header">Header text</div>

<div slot="footer" class="dialog-footer">
<div style="flex: 1"></div>
<ui5-button id="closeButton" design="Emphasized">Close</ui5-button>
Expand All @@ -415,7 +426,7 @@ <h2>Horizontal Align</h2>
<div>
<ui5-checkbox id="rtlCb" text="rtl"></ui5-checkbox>
</div>

<div id="horizontalAlignContainer">
<div id="targetOpener" class="popover10auto">
<span>Target opener</span>
Expand Down Expand Up @@ -626,7 +637,7 @@ <h2>Horizontal Align</h2>

createAndRemove.addEventListener("click", function () {
var pop = document.createElement("ui5-popover");

pop.setAttribute("open", true);
pop.setAttribute("opener", "createAndRemove");

Expand Down
51 changes: 51 additions & 0 deletions packages/main/test/pages/PopoverScale.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html class="popover1auto">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Popover</title>

<script data-ui5-config type="application/json">
{
"language": "EN",
"libs": "sap.ui.webc.main"
}
</script>


<script src="../../bundle.esm.js" type="module"></script>


<link rel="stylesheet" type="text/css" href="./styles/Popover.css">

<script>
// delete Document.prototype.adoptedStyleSheets
</script>
</head>

<body style="transform:scale(0.7); /* margin: 100px; */ background-color:gray; outline: 1px solid red;">
<ui5-button id="openDialogButton">Open Popover</ui5-button>
<br />

<ui5-popover id="hello-dialog" header-text="Dialogs are easy!" placement-type="Bottom">
<div stype="padding: 2rem; display:flex; justify-content: center;">
Hello World!
<ui5-button id="closeDialogButton">Dismiss</ui5-button>
</div>
</ui5-dialog>

<script>
const openBtn = document.getElementById("openDialogButton");
const closeBtn = document.getElementById("closeDialogButton");
const dialog = document.getElementById("hello-dialog");
openBtn.addEventListener("click", () => {
dialog.showAt(openBtn);
});
closeBtn.addEventListener("click", () => {
dialog.close();
});
</script>
</body>

</html>
Loading