From 515ab3c4c762991e24e4094c431ed95c36b85e76 Mon Sep 17 00:00:00 2001 From: "Ahmad K. Bawaneh" Date: Thu, 7 Dec 2023 11:37:16 +0300 Subject: [PATCH] fix #897 add BestRight{Up/Down}DropDirection --- .../domino/ui/menu/AbstractMenuItem.java | 6 ++++++ .../domino/ui/menu/CustomMenuItem.java | 15 +++++++++++++++ .../org/dominokit/domino/ui/menu/MenuItem.java | 13 +++++++++++++ .../domino/ui/menu/MenuItemsGroup.java | 17 ++++++++++++++++- .../dominokit/domino/ui/menu/MenuStyles.java | 1 + .../direction/BottomLeftDropDirection.java | 7 ++++--- .../direction/BottomMiddleDropDirection.java | 18 ++++++++++-------- .../direction/BottomRightDropDirection.java | 3 ++- .../menu/direction/LeftDownDropDirection.java | 16 ++++++++-------- .../direction/LeftMiddleDropDirection.java | 10 +++++----- .../ui/menu/direction/LeftUpDropDirection.java | 16 ++++++++-------- .../menu/direction/RightDownDropDirection.java | 14 +++++++------- .../direction/RightMiddleDropDirection.java | 14 +++++++------- .../menu/direction/RightUpDropDirection.java | 14 +++++++------- .../menu/direction/TopLeftDropDirection.java | 8 ++++---- .../menu/direction/TopMiddleDropDirection.java | 18 +++++++++--------- .../menu/direction/TopRightDropDirection.java | 3 ++- .../dui-components/domino-ui-menu.css | 6 ++++++ 18 files changed, 130 insertions(+), 69 deletions(-) diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/AbstractMenuItem.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/AbstractMenuItem.java index b6b40a267..f0f2de8ca 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/AbstractMenuItem.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/AbstractMenuItem.java @@ -602,6 +602,12 @@ public > T setSearchFilter(MenuSearchFilter search return (T) this; } + /** + * Check if the menu item text starts with a specific string + * + * @param character the text to check against. + * @return boolean, true if the menu item starts with the text, false otherwise. + */ public boolean startsWith(String character) { return false; } diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/CustomMenuItem.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/CustomMenuItem.java index e624643ee..7ab925b34 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/CustomMenuItem.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/CustomMenuItem.java @@ -18,6 +18,9 @@ import static java.util.Objects.isNull; import static java.util.Objects.nonNull; +import org.dominokit.domino.ui.elements.AnchorElement; +import org.dominokit.domino.ui.utils.ChildHandler; + /** * A custom menu item that extends the {@link AbstractMenuItem} with the capability to apply custom * search filters to menu items. @@ -46,6 +49,18 @@ public CustomMenuItem() { this.searchFilter = (token, caseSensitive) -> false; } + /** + * Applies a custom child handler to the link element of this menu item + * + * @param handler The child handler to apply. + * @return This menu item instance. + */ + public CustomMenuItem withClickableElement( + ChildHandler, AnchorElement> handler) { + handler.apply(this, linkElement); + return this; + } + /** * Invoked during a search operation. Displays the menu item if the token is found using the * provided {@link MenuSearchFilter}. diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItem.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItem.java index 41734ffd2..b4469d30c 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItem.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItem.java @@ -22,8 +22,10 @@ import java.util.Arrays; import java.util.Optional; import java.util.stream.Collectors; +import org.dominokit.domino.ui.elements.AnchorElement; import org.dominokit.domino.ui.elements.SmallElement; import org.dominokit.domino.ui.elements.SpanElement; +import org.dominokit.domino.ui.utils.ChildHandler; /** * Represents a menu item that can be added to a menu. Each menu item can have a text and an @@ -71,6 +73,17 @@ public MenuItem(String text) { this.searchFilter = this::containsToken; } + /** + * Applies a custom child handler to the link element of this menu item + * + * @param handler The child handler to apply. + * @return This menu item instance. + */ + public MenuItem withClickableElement(ChildHandler, AnchorElement> handler) { + handler.apply(this, linkElement); + return this; + } + /** * Constructs a menu item with the specified text and description. * diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItemsGroup.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItemsGroup.java index 7fe6a24e4..9f5c647fd 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItemsGroup.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuItemsGroup.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; +import org.dominokit.domino.ui.elements.AnchorElement; import org.dominokit.domino.ui.elements.DivElement; import org.dominokit.domino.ui.elements.UListElement; import org.dominokit.domino.ui.layout.NavBar; @@ -62,7 +63,9 @@ public MenuItemsGroup(Menu menu) { linkElement.removeCss(dui_menu_item_anchor); linkElement.addCss(dui_menu_group_header); root.appendChild(groupElement = div().addCss(dui_flex, dui_flex_col)); - groupHeader = LazyChild.of(NavBar.create().addCss(dui_order_first), bodyElement); + groupHeader = + LazyChild.of( + NavBar.create().addCss(dui_menu_group_header_nav).addCss(dui_order_first), bodyElement); itemsListElement = LazyChild.of(ul().addCss(dui_menu_items_list, dui_order_last), groupElement); } @@ -129,6 +132,18 @@ public MenuItemsGroup withItemsMenu(ChildHandler, UListElem return this; } + /** + * Applies a custom child handler to the link element of this menu item + * + * @param handler The child handler to apply. + * @return This menu item instance. + */ + public MenuItemsGroup withClickableElement( + ChildHandler, AnchorElement> handler) { + handler.apply(this, linkElement); + return this; + } + /** * Invoked during a search operation across all the menu items in this group. * diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuStyles.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuStyles.java index 927331d65..0861fd416 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuStyles.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/MenuStyles.java @@ -44,6 +44,7 @@ public interface MenuStyles { CssClass dui_menu_item_hint = () -> "dui-menu-item-hint"; CssClass dui_menu_group = () -> "dui-menu-group"; CssClass dui_menu_group_header = () -> "dui-menu-group-header"; + CssClass dui_menu_group_header_nav = () -> "dui-menu-group-header-nav"; CssClass dui_menu_drop = () -> "dui-menu-drop"; CssClass dui_menu_item_prefix = () -> "dui-menu-item-prefix"; diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomLeftDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomLeftDropDirection.java index 2daf358e2..e6c247a93 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomLeftDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomLeftDropDirection.java @@ -48,14 +48,15 @@ public void position(Element source, Element target) { delta = newRect.width - availableSpace; } + double left = (targetRect.left - (newRect.left - targetRect.left)) + - (sourceRect.width - targetRect.width) + + delta; Style.of(source) .style .setProperty( "left", px.of( - (targetRect.left - (newRect.left - targetRect.left)) - - (sourceRect.width - targetRect.width) - + delta)); + Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomMiddleDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomMiddleDropDirection.java index 6a643fb96..cc3ae731b 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomMiddleDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomMiddleDropDirection.java @@ -22,6 +22,7 @@ import static org.dominokit.domino.ui.utils.Unit.px; import elemental2.dom.DOMRect; +import elemental2.dom.DomGlobal; import elemental2.dom.Element; import org.dominokit.domino.ui.style.Style; @@ -49,24 +50,25 @@ public void position(Element source, Element target) { int innerWidth = window.innerWidth; double delta = 0; - double availableSpace = innerWidth - newTargetRect.right - window.pageXOffset; + double availableSpace = innerWidth - newTargetRect.right + (newTargetRect.width / 2) - window.pageXOffset; if (availableSpace < (newRect.width / 2)) { - delta = (newRect.width / 2) - availableSpace; + delta = (newRect.width / 2) - (newTargetRect.width / 2) - availableSpace; } elements.elementOf(source).setCssProperty("--dui-menu-drop-pin-offset", delta + "px"); + double left = newTargetRect.left + - (newRect.width / 2) + + (newTargetRect.width / 2) + + window.pageXOffset + - Math.abs(delta) + - elements.body().element().getBoundingClientRect().left; Style.of(source) .style .setProperty( "left", px.of( - newTargetRect.left - - (newRect.width / 2) - + (newTargetRect.width / 2) - + window.pageXOffset - - delta - - elements.body().element().getBoundingClientRect().left)); + Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomRightDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomRightDropDirection.java index 0741804c9..c3caaf64a 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomRightDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/BottomRightDropDirection.java @@ -47,12 +47,13 @@ public void position(Element source, Element target) { dui_dd_bottom_right.apply(source); elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + window.pageXOffset - delta; Style.of(source) .style .setProperty( "left", px.of( - (targetRect.left - (newRect.left - targetRect.left)) + window.pageXOffset - delta)); + Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftDownDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftDownDropDirection.java index 82b9465c8..ba75612d7 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftDownDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftDownDropDirection.java @@ -51,18 +51,18 @@ public void position(Element source, Element target) { elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = targetRect.left + - (newRect.left - targetRect.left) + + window.pageXOffset + - sourceRect.width + - (source.hasAttribute("dui-position-x-offset") + ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) + : 0); Style.of(source) .style .setProperty( "left", - px.of( - targetRect.left - - (newRect.left - targetRect.left) - + window.pageXOffset - - sourceRect.width - - (source.hasAttribute("dui-position-x-offset") - ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) - : 0))); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftMiddleDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftMiddleDropDirection.java index 5b32693d7..c757e3fff 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftMiddleDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftMiddleDropDirection.java @@ -45,15 +45,15 @@ public void position(Element source, Element target) { delta = ((sourceRect.height / 2) - availableUpSpace); } + double left = targetRect.top + + window.pageYOffset + - ((sourceRect.height - targetRect.height) / 2) + + delta; Style.of(source) .style .setProperty( "top", - px.of( - targetRect.top - + window.pageYOffset - - ((sourceRect.height - targetRect.height) / 2) - + delta)); + px.of(Math.max(left, 0))); Style.of(source).style.setProperty("left", px.of(targetRect.left)); diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftUpDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftUpDropDirection.java index ead0d1eaf..3174d5961 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftUpDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/LeftUpDropDirection.java @@ -51,18 +51,18 @@ public void position(Element source, Element target) { elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = targetRect.left + - (newRect.left - targetRect.left) + + window.pageXOffset + - sourceRect.width + - (source.hasAttribute("dui-position-x-offset") + ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) + : 0); Style.of(source) .style .setProperty( "left", - px.of( - targetRect.left - - (newRect.left - targetRect.left) - + window.pageXOffset - - sourceRect.width - - (source.hasAttribute("dui-position-x-offset") - ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) - : 0))); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightDownDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightDownDropDirection.java index 06671924d..1fdc4e159 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightDownDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightDownDropDirection.java @@ -52,17 +52,17 @@ public void position(Element source, Element target) { elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + + window.pageXOffset + + targetRect.width + + (source.hasAttribute("dui-position-x-offset") + ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) + : 0); Style.of(source) .style .setProperty( "left", - px.of( - (targetRect.left - (newRect.left - targetRect.left)) - + window.pageXOffset - + targetRect.width - + (source.hasAttribute("dui-position-x-offset") - ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) - : 0))); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightMiddleDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightMiddleDropDirection.java index 2a47e9898..98c3a3cca 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightMiddleDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightMiddleDropDirection.java @@ -64,17 +64,17 @@ public void position(Element source, Element target) { elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + + window.pageXOffset + + targetRect.width + + (source.hasAttribute("dui-position-x-offset") + ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) + : 0); Style.of(source) .style .setProperty( "left", - px.of( - (targetRect.left - (newRect.left - targetRect.left)) - + window.pageXOffset - + targetRect.width - + (source.hasAttribute("dui-position-x-offset") - ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) - : 0))); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightUpDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightUpDropDirection.java index 652097227..dcb44fe8d 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightUpDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/RightUpDropDirection.java @@ -59,17 +59,17 @@ public void position(Element source, Element target) { .setCssProperty("--dui-dd-position-delta", ((targetRect.top - sourceRect.top)) + "px"); elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + + window.pageXOffset + + targetRect.width + + (source.hasAttribute("dui-position-x-offset") + ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) + : 0); Style.of(source) .style .setProperty( "left", - px.of( - (targetRect.left - (newRect.left - targetRect.left)) - + window.pageXOffset - + targetRect.width - + (source.hasAttribute("dui-position-x-offset") - ? Double.parseDouble(source.getAttribute("dui-position-x-offset")) - : 0))); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopLeftDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopLeftDropDirection.java index 0d3c511ad..347ec8457 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopLeftDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopLeftDropDirection.java @@ -50,14 +50,14 @@ public void position(Element source, Element target) { elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + - (sourceRect.width - targetRect.width) + + delta; Style.of(source) .style .setProperty( "left", - px.of( - (targetRect.left - (newRect.left - targetRect.left)) - - (sourceRect.width - targetRect.width) - + delta)); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopMiddleDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopMiddleDropDirection.java index ee5154e18..6241d7424 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopMiddleDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopMiddleDropDirection.java @@ -49,23 +49,23 @@ public void position(Element source, Element target) { DOMRect newTargetRect = target.getBoundingClientRect(); double delta = 0; - double availableSpace = innerWidth - newTargetRect.right - window.pageXOffset; + double availableSpace = innerWidth - newTargetRect.right + (newTargetRect.width / 2) - window.pageXOffset; if (availableSpace < (newRect.width / 2)) { - delta = (newRect.width / 2) - availableSpace; + delta = (newRect.width / 2) - (newTargetRect.width / 2) - availableSpace; } elements.elementOf(source).setCssProperty("--dui-menu-drop-pin-offset", delta + "px"); + double left = newTargetRect.left + - (newRect.width / 2) + + (newTargetRect.width / 2) + + window.pageXOffset + - Math.abs(delta) + - elements.body().element().getBoundingClientRect().left; Style.of(source) .style .setProperty( "left", - px.of( - newTargetRect.left - - (newRect.width / 2) - + (newTargetRect.width / 2) - + window.pageXOffset - - delta - - elements.body().element().getBoundingClientRect().left)); + px.of(Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopRightDropDirection.java b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopRightDropDirection.java index 9183cdf46..374a76905 100644 --- a/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopRightDropDirection.java +++ b/domino-ui/src/main/java/org/dominokit/domino/ui/menu/direction/TopRightDropDirection.java @@ -49,12 +49,13 @@ public void position(Element source, Element target) { dui_dd_top_right.apply(source); elements.elementOf(source).setCssProperty("--dui-menu-drop-min-width", targetRect.width + "px"); DOMRect newRect = source.getBoundingClientRect(); + double left = (targetRect.left - (newRect.left - targetRect.left)) + window.pageXOffset - delta; Style.of(source) .style .setProperty( "left", px.of( - (targetRect.left - (newRect.left - targetRect.left)) + window.pageXOffset - delta)); + Math.max(left, 0))); } /** {@inheritDoc} */ diff --git a/domino-ui/src/main/resources/org/dominokit/domino/ui/public/css/domino-ui/dui-components/domino-ui-menu.css b/domino-ui/src/main/resources/org/dominokit/domino/ui/public/css/domino-ui/dui-components/domino-ui-menu.css index 02735fe01..a0184db50 100644 --- a/domino-ui/src/main/resources/org/dominokit/domino/ui/public/css/domino-ui/dui-components/domino-ui-menu.css +++ b/domino-ui/src/main/resources/org/dominokit/domino/ui/public/css/domino-ui/dui-components/domino-ui-menu.css @@ -271,6 +271,12 @@ a.dui-menu-group-header:focus, a.dui-menu-group-header { text-decoration: none; outline: none; + display: inherit; +} + +.dui-menu-group-header-nav { + border: none; + --dui-menu-header-border-width: 0; } .dui-menu-items-list .li:last-child {