Files
michaelschiemer/resources/js/core/init.js
Michael Schiemer e30753ba0e fix: resolve RedisCache array offset error and improve discovery diagnostics
- Fix RedisCache driver to handle MGET failures gracefully with fallback
- Add comprehensive discovery context comparison debug tools
- Identify root cause: WEB context discovery missing 166 items vs CLI
- WEB context missing RequestFactory class entirely (52 vs 69 commands)
- Improved exception handling with detailed binding diagnostics
2025-09-12 20:05:18 +02:00

289 lines
9.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { registerModules, activeModules } from "../modules/index.js";
import { Logger } from './logger.js';
import {useEvent} from "./useEvent";
/*import { createTrigger, destroyTrigger, destroyAllTriggers } from './scrollfx/index.js';
createTrigger({
element: 'section',
target: '.fade',
start: 'top 80%',
end: 'bottom 30%',
scrub: true,
onUpdate: (() => {
const progressMap = new WeakMap();
return (el, progress) => {
if (!el) return;
let current = progressMap.get(el) || 0;
current += (progress - current) * 0.1;
progressMap.set(el, current);
el.style.opacity = current;
el.style.transform = `translateY(${30 - 30 * current}px)`;
};
})(),
onEnter: el => el.classList.add('entered'),
onLeave: el => {
el.classList.remove('entered');
el.style.opacity = 0;
el.style.transform = 'translateY(30px)';
}
});*/
/*
let lastScrollY = window.scrollY;
const fadeElements = document.querySelectorAll('.fade-in-on-scroll');
// Observer 1: Einblenden beim Runterscrollen
const fadeInObserver = new IntersectionObserver((entries) => {
const scrollingDown = window.scrollY > lastScrollY;
lastScrollY = window.scrollY;
entries.forEach(entry => {
if (entry.isIntersecting && scrollingDown) {
entry.target.classList.add('visible');
}
});
}, {
threshold: 0.4,
rootMargin: '0px 0px -10% 0px'
});
// Observer 2: Ausblenden beim Hochscrollen
const fadeOutObserver = new IntersectionObserver((entries) => {
const scrollingUp = window.scrollY < lastScrollY;
lastScrollY = window.scrollY;
entries.forEach(entry => {
if (!entry.isIntersecting && scrollingUp) {
entry.target.classList.remove('visible');
}
});
}, {
threshold: 0.5,
rootMargin: '0% 0px 50% 0px' // früher triggern beim Hochscrollen
});
// Alle Elemente mit beiden Observern beobachten
fadeElements.forEach(el => {
fadeInObserver.observe(el);
fadeOutObserver.observe(el);
});
*/
/*
const newContent = '<h1>Neue Seite</h1>'; // dein AJAX-Inhalt z.B.
const container = document.querySelector('main');
document.startViewTransition(() => {
container.innerHTML = newContent;
});*/
import {autoLoadResponsiveVideos} from "../utils/autoLoadResponsiveVideo";
/**
* Initialize DOM elements with data-module attributes
*/
function initDataModuleElements() {
const elements = document.querySelectorAll('[data-module]');
Logger.info(`[DOMInit] Found ${elements.length} elements with data-module attributes`);
elements.forEach(element => {
const moduleName = element.dataset.module;
const moduleData = activeModules.get(moduleName);
if (!moduleData || !moduleData.mod) {
Logger.warn(`[DOMInit] Module "${moduleName}" not found or failed to initialize`);
return;
}
// Parse options from data-options attribute
let options = {};
try {
if (element.dataset.options) {
options = JSON.parse(element.dataset.options);
}
} catch (error) {
Logger.warn(`[DOMInit] Invalid JSON in data-options for ${moduleName}:`, error);
}
// Initialize the module on this element
try {
const moduleInstance = moduleData.mod;
// Check for element-specific init method first, then fallback to general init
if (typeof moduleInstance.initElement === 'function') {
const result = moduleInstance.initElement(element, options);
Logger.info(`[DOMInit] Initialized ${moduleName} on element:`, element);
// Store reference for cleanup
element._moduleInstance = result;
element._moduleName = moduleName;
} else if (typeof moduleInstance.init === 'function') {
const result = moduleInstance.init(element, options);
Logger.info(`[DOMInit] Initialized ${moduleName} on element:`, element);
// Store reference for cleanup
element._moduleInstance = result;
element._moduleName = moduleName;
} else {
Logger.warn(`[DOMInit] Module ${moduleName} has no init method for DOM elements`);
}
} catch (error) {
Logger.error(`[DOMInit] Failed to initialize ${moduleName} on element:`, error, element);
}
});
}
/**
* Initialize SPA Router for seamless navigation
*/
function initSPARouter() {
const spaRouterModule = activeModules.get('spa-router');
if (!spaRouterModule || !spaRouterModule.mod) {
Logger.info('[Init] SPA Router module not available, skipping');
return;
}
try {
// Initialize SPA Router with default configuration
const router = spaRouterModule.mod.init({
containerSelector: 'main',
enableTransitions: true,
transitionDuration: 300
});
// Make functions globally available for re-initialization
window.initAutoFormHandling = initAutoFormHandling;
window.initDataModuleElements = initDataModuleElements;
Logger.info('[Init] SPA Router initialized successfully');
} catch (error) {
Logger.error('[Init] Failed to initialize SPA Router:', error);
}
}
/**
* Auto-initialize all forms with form-handling (opt-out approach)
*/
function initAutoFormHandling() {
// Find all forms except those explicitly opting out and those already enhanced
const forms = document.querySelectorAll('form:not([data-form-handling="false"]):not([data-auto-enhanced])');
Logger.info(`[AutoForms] Found ${forms.length} forms for auto-enhancement`);
if (forms.length === 0) return;
// Check if form-handling module is available
const formHandlingModule = activeModules.get('form-handling');
if (!formHandlingModule || !formHandlingModule.mod) {
Logger.warn('[AutoForms] form-handling module not available, skipping auto-init');
return;
}
forms.forEach(form => {
// Skip forms that already have explicit data-module
if (form.hasAttribute('data-module')) {
Logger.info(`[AutoForms] Skipping form with explicit data-module:`, form);
return;
}
// Skip forms that are already enhanced (double-check)
if (form.hasAttribute('data-auto-enhanced')) {
return;
}
// Parse options from data-form-options attribute
let options = {};
try {
if (form.dataset.formOptions) {
options = JSON.parse(form.dataset.formOptions);
}
} catch (error) {
Logger.warn('[AutoForms] Invalid JSON in data-form-options:', error);
}
// Set default options for auto-enhanced forms
const autoOptions = {
validateOnSubmit: true,
validateOnBlur: false,
validateOnInput: false,
showInlineErrors: true,
ajaxSubmit: true,
enableStateTracking: false, // Conservative default
...options
};
// Initialize form handling
try {
// Use initElement for DOM-specific initialization
const result = formHandlingModule.mod.initElement ?
formHandlingModule.mod.initElement(form, autoOptions) :
formHandlingModule.mod.init(form, autoOptions);
Logger.info('[AutoForms] Auto-enhanced form:', {
id: form.id || 'unnamed',
action: form.action || 'none',
method: form.method || 'get',
elements: form.elements.length
});
// Mark as auto-enhanced
form.setAttribute('data-auto-enhanced', 'true');
form._moduleInstance = result;
form._moduleName = 'form-handling';
} catch (error) {
Logger.error('[AutoForms] Failed to auto-enhance form:', error, form);
}
});
}
/**
* Initialize the application
* Sets up all modules and core functionality
* @async
* @function initApp
* @returns {Promise<void>}
*/
export async function initApp() {
await registerModules();
// Initialize DOM elements after modules are registered
initDataModuleElements();
// Auto-enhance all forms with form-handling
initAutoFormHandling();
// Initialize SPA Router for seamless navigation
initSPARouter();
autoLoadResponsiveVideos();
/*initNoiseToggle({
selector: '.noise-overlay',
toggleKey: 'g', // Taste zum Umschalten
className: 'grainy', // Klasse auf <body>
enableTransition: true // Smooth fade
});
fadeScrollTrigger('.fade');
zoomScrollTrigger('.zoomed');
fixedZoomScrollTrigger('h1');*/
}