You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by hn...@apache.org on 2025/05/22 11:48:08 UTC
(myfaces-tobago) 01/02: fix(dropdown): position
This is an automated email from the ASF dual-hosted git repository.
hnoeth pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git
commit 9ca59c6b45ac39bdc54089b4f3d7e056938dd4cb
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Tue May 20 09:36:08 2025 +0200
fix(dropdown): position
* add test
* fix position if on the right
Issue: TOBAGO-2422
---
.../DropdownMenuPosition.test.js | 15 ++++++++
.../DropdownMenuPosition.xhtml | 17 +++++++++
.../src/main/ts/tobago-dropdown-menu.ts | 43 +++++++++++++---------
3 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.test.js
index 8636dffade..088ccc16d5 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.test.js
@@ -18,6 +18,21 @@
import {elementByIdFn, innerHeight, querySelectorFn, scrollTo} from "/script/tobago-test.js";
import {JasmineTestTool} from "/tobago/test/tobago-test-tool.js";
+it("Button dropdown on the right", function (done) {
+ const button = elementByIdFn("page:mainForm:buttonDropdownRight::command");
+ const dropdownMenu = querySelectorFn(".tobago-dropdown-menu[name='page:mainForm:buttonDropdownRight']");
+
+ const test = new JasmineTestTool(done);
+ test.event("click", button, () => dropdownMenu().classList.contains("show"));
+ test.waitMs(100);
+ test.do(() => expect(dropdownMenu().classList).toContain("show"));
+ test.do(() => expect(dropdownMenu().getBoundingClientRect().left).toBeGreaterThan(0));
+ test.do(() => expect(dropdownMenu().getBoundingClientRect().left).toBeLessThan(window.innerWidth));
+ test.do(() => expect(dropdownMenu().getBoundingClientRect().right).toBeGreaterThan(0));
+ test.do(() => expect(dropdownMenu().getBoundingClientRect().right).toBeLessThan(window.innerWidth));
+ test.start();
+});
+
it("default - SelectOneList: upper half", function (done) {
const tobagoHeader = querySelectorFn("tobago-header.sticky-top");
const selectOneList = elementByIdFn("page:mainForm:defaultSelectOneList");
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.xhtml
index cd96042d05..a37ae1f303 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/900-test/4200-dropdown/dropdown-menu-position/DropdownMenuPosition.xhtml
@@ -23,6 +23,23 @@
xmlns:tc="http://myfaces.apache.org/tobago/component"
xmlns:ui="jakarta.faces.facelets">
+ <tc:header>
+ <tc:style position="fixed" top="60px" left="0" width="100%" customClass="blue"/>
+ <tc:bar>
+ <f:facet name="brand">
+ BRAND
+ </f:facet>
+ CONTENT OF TC:BAR
+ <f:facet name="after">
+ <tc:button id="buttonDropdownRight" label="X" omit="true">
+ <tc:link
+ label="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."
+ omit="true"/>
+ </tc:button>
+ </f:facet>
+ </tc:bar>
+ </tc:header>
+
<tc:panel>
<tc:style height="1000px"/>
This is a 1000px height panel to make sure the components for testing can be at the top of the browser window.
diff --git a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-dropdown-menu.ts b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-dropdown-menu.ts
index 905726ef8c..c799a661dc 100644
--- a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-dropdown-menu.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-dropdown-menu.ts
@@ -140,23 +140,11 @@ export class DropdownMenu {
const refElementRect = this.referenceElement.getBoundingClientRect();
//calc horizontal positioning and max-width
- const rightBorder = this.body.offsetWidth;
- switch (this.alignment) {
- case DropdownMenuAlignment.start:
- case DropdownMenuAlignment.centerFullWidth:
- this.dropdownMenuElement.style.left = "0px";
- this.dropdownMenuElement.style.left = (refElementRect.left - this.dropdownRect.left) + "px";
- this.dropdownMenuElement.style.right = null;
- this.dropdownMenuElement.style.maxWidth = rightBorder - refElementRect.left
- - parseFloat(getComputedStyle(this.dropdownMenuElement).marginRight) + "px";
- break;
- case DropdownMenuAlignment.end:
- this.dropdownMenuElement.style.left = null;
- this.dropdownMenuElement.style.right = "0px";
- this.dropdownMenuElement.style.right = (this.dropdownRect.right - refElementRect.right) + "px";
- this.dropdownMenuElement.style.maxWidth = refElementRect.right
- - parseFloat(getComputedStyle(this.dropdownMenuElement).marginLeft) + "px";
- break;
+ this.calcHorizontalPositioningAndMaxWidth(refElementRect, this.alignment);
+ if (this.dropdownMenuElement.offsetWidth - 1 > parseInt(this.dropdownMenuElement.style.maxWidth)
+ && (window.innerWidth / 2) <= refElementRect.left + (refElementRect.right - refElementRect.left)) {
+ // Content of dropdown is too big and reference element is on the right side; do DropdownMenuAlignment.end
+ this.calcHorizontalPositioningAndMaxWidth(refElementRect, DropdownMenuAlignment.end);
}
//calc width
@@ -196,6 +184,27 @@ export class DropdownMenu {
}
}
+ private calcHorizontalPositioningAndMaxWidth(refElementRect: DOMRect, alignment: DropdownMenuAlignment): void {
+ const rightBorder = this.body.offsetWidth;
+ switch (alignment) {
+ case DropdownMenuAlignment.start:
+ case DropdownMenuAlignment.centerFullWidth:
+ this.dropdownMenuElement.style.left = "0px";
+ this.dropdownMenuElement.style.left = (refElementRect.left - this.dropdownRect.left) + "px";
+ this.dropdownMenuElement.style.right = null;
+ this.dropdownMenuElement.style.maxWidth = rightBorder - refElementRect.left
+ - parseFloat(getComputedStyle(this.dropdownMenuElement).marginRight) + "px";
+ break;
+ case DropdownMenuAlignment.end:
+ this.dropdownMenuElement.style.left = null;
+ this.dropdownMenuElement.style.right = "0px";
+ this.dropdownMenuElement.style.right = (this.dropdownRect.right - refElementRect.right) + "px";
+ this.dropdownMenuElement.style.maxWidth = refElementRect.right
+ - parseFloat(getComputedStyle(this.dropdownMenuElement).marginLeft) + "px";
+ break;
+ }
+ }
+
private get body(): HTMLElement {
const root = document.getRootNode() as ShadowRoot | Document;
return root.querySelector("body");