diff --git a/RELEASE_NOTES_v2.2.59.md b/RELEASE_NOTES_v2.2.59.md new file mode 100644 index 0000000..1750ca3 --- /dev/null +++ b/RELEASE_NOTES_v2.2.59.md @@ -0,0 +1,16 @@ +# Release Notes v2.2.59 + +Dato: 2026-03-18 + +## Fokus +Stabil scroll/navigation i SAG-faner, saa bruger lander ved reelt indhold i den valgte fane. + +## Aendringer +- Fjernet DOM-reordering af tab-pane elementer i SAG detaljesiden. +- Ny scroll-logik: ved faneskift scrolles til foerste meningsfulde indholdselement i aktiv fane. +- Scroll-offset tager hoejde for navbar-hoejde. +- Deep-link (`?tab=...`) bruger nu samme robuste scroll-adfaerd. + +## Berorte filer +- app/modules/sag/templates/detail.html +- RELEASE_NOTES_v2.2.59.md diff --git a/app/modules/sag/templates/detail.html b/app/modules/sag/templates/detail.html index f2dac6f..3f81f15 100644 --- a/app/modules/sag/templates/detail.html +++ b/app/modules/sag/templates/detail.html @@ -2208,21 +2208,23 @@ let selectedRelationCaseId = null; const caseTypeKey = "{{ (case.template_key or case.type or 'ticket')|lower }}"; - function promoteCaseTabPane(tabId) { + function scrollToCaseTabContent(tabId) { if (!tabId) return; - const tabContent = document.getElementById('caseTabsContent'); - const pane = document.getElementById(tabId); - if (!tabContent || !pane || !tabContent.contains(pane)) return; - if (tabContent.firstElementChild === pane) return; - tabContent.insertBefore(pane, tabContent.firstElementChild); - } - function scrollToCaseTabs() { - const tabs = document.getElementById('caseTabs'); - if (!tabs) return; - const offset = 110; - const targetTop = tabs.getBoundingClientRect().top + window.pageYOffset - offset; - window.scrollTo({ top: Math.max(0, targetTop), behavior: 'smooth' }); + const pane = document.getElementById(tabId); + if (!pane) return; + + const firstContent = pane.querySelector( + '.card, .row, .alert, .table-responsive, .list-group, form, [data-module]' + ); + const target = firstContent || pane; + + const navbar = document.querySelector('.navbar'); + const navHeight = navbar ? navbar.getBoundingClientRect().height : 0; + const offset = navHeight + 24; + const top = target.getBoundingClientRect().top + window.pageYOffset - offset; + + window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' }); } window.moduleDisplayNames = { @@ -2323,10 +2325,7 @@ console.error('Tab data reload failed:', tabLoadError); } - requestAnimationFrame(() => { - promoteCaseTabPane(tabId); - scrollToCaseTabs(); - }); + requestAnimationFrame(() => scrollToCaseTabContent(tabId)); }); } @@ -7724,8 +7723,7 @@ if (tabBtn) { setTimeout(() => { bootstrap.Tab.getOrCreateInstance(tabBtn).show(); - promoteCaseTabPane(tabParam); - scrollToCaseTabs(); + scrollToCaseTabContent(tabParam); }, 300); } }