Tutorial: Alle Demos mit _runDemo() absichern gegen haengenbleibende Navigation
Neuer Helfer _runDemo(fn): Fuehrt async Demo-Methoden aus und faengt alle Fehler ab. Bei Fehler wird _demoRunning zurueckgesetzt und _enableNavAfterDemo aufgerufen, sodass der Weiter-Button immer erscheint. Alle 12 Demo-Aufrufe (FormTitleDesc, TypeSwitch, FormSources, FormVisibility, FormRefresh, FormRetention, FormNotifications, MapDemo, Drag, Resize, SourcesInfoIcon, SourcesActions) verwenden jetzt _runDemo statt direktem Aufruf. Zusaetzlich: - _cursorToElement gibt sichere Fallback-Koordinaten zurueck wenn Element nicht sichtbar (getBoundingClientRect width/height = 0) - _simulateFormTitleDesc wartet 600ms auf Modal-Rendering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -764,7 +764,7 @@
|
||||
<script src="/static/js/api_network.js?v=20260316a"></script>
|
||||
<script src="/static/js/network-graph.js?v=20260316a"></script>
|
||||
<script src="/static/js/app_network.js?v=20260316a"></script>
|
||||
<script src="/static/js/tutorial.js?v=20260316r"></script>
|
||||
<script src="/static/js/tutorial.js?v=20260316s"></script>
|
||||
<script src="/static/js/chat.js?v=20260316f"></script>
|
||||
<script>document.addEventListener("DOMContentLoaded",function(){Chat.init();Tutorial.init()});</script>
|
||||
|
||||
|
||||
@@ -493,6 +493,17 @@ const Tutorial = {
|
||||
this._stepTimers = [];
|
||||
},
|
||||
|
||||
// Sichere Demo-Ausfuehrung: Faengt Fehler ab und stellt Navigation sicher
|
||||
_runDemo(fn) {
|
||||
var self = this;
|
||||
fn.call(this).catch(function(e) {
|
||||
self._hideCursor();
|
||||
self._clearSubHighlights();
|
||||
self._demoRunning = false;
|
||||
self._enableNavAfterDemo();
|
||||
});
|
||||
},
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Scroll-Helfer: Element in den sichtbaren Bereich scrollen
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -575,7 +586,7 @@ const Tutorial = {
|
||||
if (modalBody) modalBody.scrollTop = 0;
|
||||
var t = document.getElementById('inc-title'); if (t) t.value = '';
|
||||
var d = document.getElementById('inc-description'); if (d) d.value = '';
|
||||
Tutorial._simulateFormTitleDesc();
|
||||
Tutorial._runDemo(Tutorial._simulateFormTitleDesc);
|
||||
},
|
||||
onExit: function() {
|
||||
Tutorial._clearSubHighlights();
|
||||
@@ -600,7 +611,7 @@ const Tutorial = {
|
||||
if (modalBody) modalBody.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
Tutorial._stepTimeout(function() {
|
||||
Tutorial._highlightSub('#inc-type');
|
||||
Tutorial._simulateTypeSwitch();
|
||||
Tutorial._runDemo(Tutorial._simulateTypeSwitch);
|
||||
}, 500);
|
||||
},
|
||||
onExit: function() {
|
||||
@@ -624,7 +635,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';
|
||||
Tutorial._simulateFormSources();
|
||||
Tutorial._runDemo(Tutorial._simulateFormSources);
|
||||
},
|
||||
onExit: function() {
|
||||
Tutorial._clearSubHighlights();
|
||||
@@ -645,7 +656,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';
|
||||
Tutorial._simulateFormVisibility();
|
||||
Tutorial._runDemo(Tutorial._simulateFormVisibility);
|
||||
},
|
||||
onExit: function() {
|
||||
Tutorial._clearSubHighlights();
|
||||
@@ -666,7 +677,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';
|
||||
Tutorial._simulateFormRefresh();
|
||||
Tutorial._runDemo(Tutorial._simulateFormRefresh);
|
||||
},
|
||||
onExit: function() {
|
||||
Tutorial._clearSubHighlights();
|
||||
@@ -687,7 +698,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';
|
||||
Tutorial._simulateFormRetention();
|
||||
Tutorial._runDemo(Tutorial._simulateFormRetention);
|
||||
},
|
||||
onExit: function() {
|
||||
Tutorial._clearSubHighlights();
|
||||
@@ -709,7 +720,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';
|
||||
Tutorial._simulateFormNotifications();
|
||||
Tutorial._runDemo(Tutorial._simulateFormNotifications);
|
||||
},
|
||||
onExit: function() {
|
||||
var overlay = document.getElementById('modal-new');
|
||||
@@ -970,7 +981,7 @@ const Tutorial = {
|
||||
position: 'right',
|
||||
disableNav: true,
|
||||
onEnter: function() {
|
||||
Tutorial._simulateDrag();
|
||||
Tutorial._runDemo(Tutorial._simulateDrag);
|
||||
},
|
||||
},
|
||||
// 19 - Resize Demo
|
||||
@@ -984,7 +995,7 @@ const Tutorial = {
|
||||
position: 'left',
|
||||
disableNav: true,
|
||||
onEnter: function() {
|
||||
Tutorial._simulateResize();
|
||||
Tutorial._runDemo(Tutorial._simulateResize);
|
||||
},
|
||||
},
|
||||
// 20 - Theme
|
||||
@@ -1044,7 +1055,7 @@ const Tutorial = {
|
||||
}
|
||||
if (overlay) overlay.style.zIndex = '9002';
|
||||
Tutorial._stepTimeout(function() {
|
||||
Tutorial._simulateSourcesInfoIcon();
|
||||
Tutorial._runDemo(Tutorial._simulateSourcesInfoIcon);
|
||||
}, 1500);
|
||||
},
|
||||
onExit: function() {
|
||||
@@ -1075,7 +1086,7 @@ const Tutorial = {
|
||||
}
|
||||
}
|
||||
if (overlay) overlay.style.zIndex = '9002';
|
||||
Tutorial._simulateSourcesActions();
|
||||
Tutorial._runDemo(Tutorial._simulateSourcesActions);
|
||||
},
|
||||
onExit: function() {
|
||||
var overlay = document.getElementById('modal-sources');
|
||||
@@ -1594,7 +1605,7 @@ const Tutorial = {
|
||||
}
|
||||
// Nach Zoom: Demo starten
|
||||
setTimeout(function() {
|
||||
self._simulateMapDemo();
|
||||
self._runDemo(self._simulateMapDemo);
|
||||
}, 3200);
|
||||
}, 1200);
|
||||
},
|
||||
@@ -1680,8 +1691,9 @@ const Tutorial = {
|
||||
// Helfer: Cursor zu einem Element bewegen
|
||||
async _cursorToElement(selector, fromX, fromY) {
|
||||
var el = document.querySelector(selector);
|
||||
if (!el) return { x: fromX, y: fromY };
|
||||
if (!el) return { x: fromX || 400, y: fromY || 300 };
|
||||
var rect = el.getBoundingClientRect();
|
||||
if (!rect.width && !rect.height) return { x: fromX || 400, y: fromY || 300 };
|
||||
var tx = rect.left + Math.min(rect.width / 2, 60);
|
||||
var ty = rect.top + rect.height / 2;
|
||||
if (fromX !== undefined && fromY !== undefined) {
|
||||
@@ -1707,6 +1719,8 @@ const Tutorial = {
|
||||
// -----------------------------------------------------------------------
|
||||
async _simulateFormTitleDesc() {
|
||||
this._demoRunning = true;
|
||||
// Warten bis Modal vollstaendig gerendert
|
||||
await this._wait(600);
|
||||
var titleInput = document.getElementById('inc-title');
|
||||
var descInput = document.getElementById('inc-description');
|
||||
if (!titleInput) { this._demoRunning = false; this._enableNavAfterDemo(); return; }
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren