From bcf4d5c47f7e4c5ea6b27d8eaefd357683f94f75 Mon Sep 17 00:00:00 2001 From: Stephen Abello Date: Fri, 28 Aug 2026 15:03:45 +0200 Subject: [PATCH] Avoid uid colliding in DOM ids --- .../UI/Base/Component/Button/ButtonUIBlockFactory.php | 10 ++++++++-- .../ActivityPanelAction/ActivityPanelAction.php | 11 ++++++++++- .../TopBar/TopBarQuickAction/TopBarQuickAction.php | 11 ++++++++++- .../base/components/button/separator/layout.html.twig | 8 ++++++-- .../activity-action/activity-action-js.html.twig | 1 + .../activity-action-separator.html.twig | 3 ++- .../activity-action/activity-action-url.html.twig | 1 + .../top-bar-quick-action-js.html.twig | 1 + .../top-bar-quick-action-separator.html.twig | 1 + .../top-bar-quick-action-url.html.twig | 1 + 10 files changed, 41 insertions(+), 7 deletions(-) diff --git a/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php b/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php index 5283ccf2f1..0b037a1dd0 100644 --- a/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php +++ b/sources/Application/UI/Base/Component/Button/ButtonUIBlockFactory.php @@ -407,6 +407,7 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory $oButton->SetColor($sColor); $oButton->SetAriaAttributes($oPopupItem->GetAriaAttributes()->GetAttributes()); $oButton->SetDataAttributes($oPopupItem->GetDataAttributes()->GetAttributes()); + $oButton->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oButton; } elseif ($oPopupItem instanceof URLPopupMenuItem) { @@ -426,11 +427,13 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory $oButton->SetColor($sColor); $oButton->SetAriaAttributes($oPopupItem->GetAriaAttributes()->GetAttributes()); $oButton->SetDataAttributes($oPopupItem->GetDataAttributes()->GetAttributes()); + $oButton->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oButton; } elseif ($oPopupItem instanceof SeparatorPopupMenuItem) { - $oSeparator = new ButtonSeparator(utils::GetSafeId($oPopupItem->GetUID(), true)); + $oSeparator = new ButtonSeparator(); $oSeparator->SetCSSClasses($oPopupItem->GetCssClasses()); + $oSeparator->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oSeparator; } @@ -466,6 +469,7 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory $oButton->AddMultipleJsFilesRelPaths($oPopupItem->GetLinkedScripts()); $oButton->SetAriaAttributes($oPopupItem->GetAriaAttributes()->GetAttributes()); $oButton->SetDataAttributes($oPopupItem->GetDataAttributes()->GetAttributes()); + $oButton->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oButton; } elseif ($oPopupItem instanceof URLPopupMenuItem) { @@ -488,11 +492,13 @@ class ButtonUIBlockFactory extends AbstractUIBlockFactory } $oButton->SetAriaAttributes($oPopupItem->GetAriaAttributes()->GetAttributes()); $oButton->SetDataAttributes($oPopupItem->GetDataAttributes()->GetAttributes()); + $oButton->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oButton; } elseif ($oPopupItem instanceof SeparatorPopupMenuItem) { - $oSeparator = new ButtonSeparator(utils::GetSafeId($oPopupItem->GetUID(), true)); + $oSeparator = new ButtonSeparator(); $oSeparator->SetCSSClasses($oPopupItem->GetCssClasses()); + $oSeparator->AddDataAttribute('uid', $oPopupItem->GetUID()); return $oSeparator; } diff --git a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelAction.php b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelAction.php index 6c47d49efd..c5377727ba 100644 --- a/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelAction.php +++ b/sources/Application/UI/Base/Layout/ActivityPanel/ActivityPanelAction/ActivityPanelAction.php @@ -48,13 +48,22 @@ abstract class ActivityPanelAction extends UIBlock public function __construct(string $sLabel, string $sIconClass, ?string $sTooltip, string $sUid) { - parent::__construct(utils::GetSafeId($sUid, true)); + // UID is necessary for parent ID generation, we set it first $this->sUid = $sUid; + parent::__construct(); $this->sLabel = $sLabel; $this->sIconClass = $sIconClass; $this->sTooltip = $sTooltip; } + /** + * @inheritDoc + */ + protected function GenerateId(): string + { + return parent::GenerateId().'--'.utils::GetSafeId($this->sUid); + } + public function SetPopupItems(array $aPopupItems): static { $this->aPopupItems = $aPopupItems; diff --git a/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickAction.php b/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickAction.php index 81e9af2198..6dc51584ab 100644 --- a/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickAction.php +++ b/sources/Application/UI/Base/Layout/TopBar/TopBarQuickAction/TopBarQuickAction.php @@ -56,13 +56,22 @@ abstract class TopBarQuickAction extends UIBlock */ public function __construct(string $sLabel, string $sIconClass, ?string $sTooltip, string $sUid) { - parent::__construct(utils::GetSafeId($sUid, true)); + // UID is necessary for parent ID generation, we set it first $this->sUid = $sUid; + parent::__construct(); $this->sLabel = $sLabel; $this->sIconClass = $sIconClass; $this->sTooltip = $sTooltip; } + /** + * @inheritDoc + */ + protected function GenerateId(): string + { + return parent::GenerateId().'--'.utils::GetSafeId($this->sUid); + } + public function GetAriaAttributes(): array { $aDefaultValues = []; diff --git a/templates/base/components/button/separator/layout.html.twig b/templates/base/components/button/separator/layout.html.twig index e94ecc5968..f7afc81e62 100644 --- a/templates/base/components/button/separator/layout.html.twig +++ b/templates/base/components/button/separator/layout.html.twig @@ -5,7 +5,11 @@ class="{{ oUIBlock.GetBlocksInheritanceCSSClassesAsString() }} {% if oUIBlock.GetAdditionalCSSClassesAsString() %}{{ oUIBlock.GetAdditionalCSSClassesAsString() }}{% endif %} {% if oUIBlock.IsHidden() %}ibo-is-hidden{% endif %}" - data-role="ibo-button-separator"> + data-role="ibo-button-separator" + {% if oUIBlock.GetDataAttributes() %} + {% for sName, sValue in oUIBlock.GetDataAttributes() %} + data-{{ sName }}="{{ sValue }}" + {% endfor %} + {% endif %}> {% endapply %} - diff --git a/templates/base/layouts/activity-panel/activity-action/activity-action-js.html.twig b/templates/base/layouts/activity-panel/activity-action/activity-action-js.html.twig index 80c7e7b73d..4d75ad3034 100644 --- a/templates/base/layouts/activity-panel/activity-action/activity-action-js.html.twig +++ b/templates/base/layouts/activity-panel/activity-action/activity-action-js.html.twig @@ -2,6 +2,7 @@ id="{{ oUIBlock.GetId() }}" class="{{ oUIBlock.GetBlocksInheritanceCSSClassesAsString() }} {{ oUIBlock.GetAdditionalCSSClassesAsString() }} ibo-activity-panel--activity-action" data-role="ibo-activity-panel--activity-action" + data-uid="{{ oUIBlock.GetUID() }}" {% if oUIBlock.GetDataAttributes() %} {% for sName, sValue in oUIBlock.GetDataAttributes() %} data-{{ sName }}="{{ sValue }}" diff --git a/templates/base/layouts/activity-panel/activity-action/activity-action-separator.html.twig b/templates/base/layouts/activity-panel/activity-action/activity-action-separator.html.twig index ac56463f54..387bdc0505 100644 --- a/templates/base/layouts/activity-panel/activity-action/activity-action-separator.html.twig +++ b/templates/base/layouts/activity-panel/activity-action/activity-action-separator.html.twig @@ -1,4 +1,5 @@ + data-role="ibo-activity-panel--activity-action-separator" + data-uid="{{ oUIBlock.GetUID() }}"> diff --git a/templates/base/layouts/activity-panel/activity-action/activity-action-url.html.twig b/templates/base/layouts/activity-panel/activity-action/activity-action-url.html.twig index c2da9a515a..9564cd3629 100644 --- a/templates/base/layouts/activity-panel/activity-action/activity-action-url.html.twig +++ b/templates/base/layouts/activity-panel/activity-action/activity-action-url.html.twig @@ -2,6 +2,7 @@ id="{{ oUIBlock.GetId() }}" class="{{ oUIBlock.GetBlocksInheritanceCSSClassesAsString() }} {{ oUIBlock.GetAdditionalCSSClassesAsString() }} ibo-activity-panel--activity-action" data-role="ibo-activity-panel--activity-action" + data-uid="{{ oUIBlock.GetUID() }}" {% if oUIBlock.GetDataAttributes() %} {% for sName, sValue in oUIBlock.GetDataAttributes() %} data-{{ sName }}="{{ sValue }}" diff --git a/templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.html.twig b/templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.html.twig index c71c6948e8..9427345d6f 100644 --- a/templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.html.twig +++ b/templates/base/layouts/top-bar/top-bar-quick-action/top-bar-quick-action-js.html.twig @@ -3,6 +3,7 @@ data-role="ibo-top-bar-quick-action">