From d2afd102e020799ea727e79846d568759d7f9c1d Mon Sep 17 00:00:00 2001 From: Claude Dev Date: Mon, 23 Mar 2026 21:55:48 +0100 Subject: [PATCH] Tutorial: Modal-Felder zentriert scrollen in Schritten 5-10 - _scrollModalTo scrollt Element in die Mitte des sichtbaren Bereichs - _scrollModalAndReposition repositioniert Bubble nach Scroll - Alle Modal-Simulationen nutzen zentriertes Scrolling - Schritt 4+5 nutzen jetzt _scrollModalTo statt manuelles scrollTo --- src/static/js/tutorial.js | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/static/js/tutorial.js b/src/static/js/tutorial.js index f392e54..e0e0739 100644 --- a/src/static/js/tutorial.js +++ b/src/static/js/tutorial.js @@ -603,8 +603,7 @@ const Tutorial = { var overlay = document.getElementById('modal-new'); if (overlay && !overlay.classList.contains('active')) overlay.classList.add('active'); if (overlay) overlay.style.zIndex = '9002'; - var modalBody = document.querySelector('#modal-new .modal-body'); - if (modalBody) modalBody.scrollTop = 0; + Tutorial._scrollModalTo('#inc-title'); var t = document.getElementById('inc-title'); if (t) t.value = ''; var d = document.getElementById('inc-description'); if (d) d.value = ''; Tutorial._runDemo(Tutorial._simulateFormTitleDesc); @@ -629,12 +628,11 @@ const Tutorial = { var overlay = document.getElementById('modal-new'); if (overlay && !overlay.classList.contains('active')) overlay.classList.add('active'); if (overlay) overlay.style.zIndex = '9002'; - var modalBody = document.querySelector('#modal-new .modal-body'); - if (modalBody) modalBody.scrollTo({ top: 0, behavior: 'smooth' }); + Tutorial._scrollModalTo('#inc-type'); Tutorial._stepTimeout(function() { Tutorial._highlightSub('#inc-type'); Tutorial._runDemo(Tutorial._simulateTypeSwitch); - }, 500); + }, 600); }, onExit: function() { var sel = document.getElementById('inc-type'); @@ -1807,21 +1805,27 @@ const Tutorial = { var el = document.querySelector(selector); var modalBody = document.querySelector('#modal-new .modal-body'); if (!el || !modalBody) return Promise.resolve(); - // Element-Position relativ zum sichtbaren Modal-Bereich + // Element zentriert im sichtbaren Modal-Bereich anzeigen var elRect = el.getBoundingClientRect(); var bodyRect = modalBody.getBoundingClientRect(); - // Pruefen ob Element bereits sichtbar - if (elRect.top >= bodyRect.top && elRect.bottom <= bodyRect.bottom) { - return Promise.resolve(); - } - // Scroll-Ziel: Element mit Abstand oben im sichtbaren Bereich + var bodyVisibleH = bodyRect.height; var offset = elRect.top - bodyRect.top + modalBody.scrollTop; - var targetScroll = offset - 30; + var elCenter = offset + elRect.height / 2; + var targetScroll = elCenter - bodyVisibleH / 2; modalBody.scrollTo({ top: Math.max(0, targetScroll), behavior: 'smooth' }); - // Warten bis Scroll abgeschlossen return new Promise(function(resolve) { setTimeout(resolve, 500); }); }, + // Helfer: Modal scrollen UND Bubble neu positionieren + async _scrollModalAndReposition(selector) { + await this._scrollModalTo(selector); + // Bubble neu positionieren nach Scroll + if (this._currentStep >= 0) { + var step = this._steps[this._currentStep]; + this._positionBubble(step); + } + }, + // ----------------------------------------------------------------------- // Step 3: Titel + Beschreibung // ----------------------------------------------------------------------- @@ -1943,7 +1947,7 @@ const Tutorial = { // ----------------------------------------------------------------------- async _simulateFormSources() { this._demoRunning = true; - await this._scrollModalTo('#inc-international'); + await this._scrollModalAndReposition('#inc-international'); await this._wait(400); // International-Toggle highlighten @@ -1977,7 +1981,7 @@ const Tutorial = { // ----------------------------------------------------------------------- async _simulateFormVisibility() { this._demoRunning = true; - await this._scrollModalTo('#inc-visibility'); + await this._scrollModalAndReposition('#inc-visibility'); await this._wait(400); var checkbox = document.getElementById('inc-visibility'); @@ -2009,7 +2013,7 @@ const Tutorial = { // ----------------------------------------------------------------------- async _simulateFormRefresh() { this._demoRunning = true; - await this._scrollModalTo('#inc-refresh-mode'); + await this._scrollModalAndReposition('#inc-refresh-mode'); await this._wait(400); var refreshSelect = document.getElementById('inc-refresh-mode'); @@ -2045,7 +2049,7 @@ const Tutorial = { // ----------------------------------------------------------------------- async _simulateFormRetention() { this._demoRunning = true; - await this._scrollModalTo('#inc-retention'); + await this._scrollModalAndReposition('#inc-retention'); await this._wait(400); var retentionInput = document.getElementById('inc-retention'); @@ -2066,7 +2070,7 @@ const Tutorial = { // ----------------------------------------------------------------------- async _simulateFormNotifications() { this._demoRunning = true; - await this._scrollModalTo('#inc-notify-summary'); + await this._scrollModalAndReposition('#inc-notify-summary'); await this._wait(400); var checks = ['#inc-notify-summary', '#inc-notify-new-articles', '#inc-notify-status-change'];