function createRequiredProgress({ container, progress, onChange }) { let total = 0; let filled = 0; const body = typeof container === 'string' ? document.querySelector(container) : container; const progressEl = typeof progress === 'string' ? document.querySelector(progress) : progress; if (!body || !progressEl) return; function isElementVisible(el) { const style = window.getComputedStyle(el); return el.offsetParent !== null && style.opacity !== '0'; } function updateRequiredProgress() { const requiredElements = Array.from( body.querySelectorAll('input[required], select[required], textarea[required]') ).filter(isElementVisible); total = requiredElements.length; filled = requiredElements.filter(el => el.classList.contains('is-required-filled') ).length; progressEl.textContent = `${filled} / ${total} Pflichtfelder ausgefüllt`; progressEl.classList.toggle('complete', filled === total); progressEl.classList.toggle('incomplete', filled !== total); } function updateRequiredState(el) { const isEmpty = (el instanceof HTMLSelectElement && !el.value) || (el instanceof HTMLInputElement && el.type !== 'checkbox' && !el.value.trim()) || (el instanceof HTMLTextAreaElement && !el.value.trim()); el.classList.toggle('is-required-empty', isEmpty); el.classList.toggle('is-required-filled', !isEmpty); updateRequiredProgress(); if (typeof onChange === 'function') { onChange({ element: el, isEmpty, isFilled: !isEmpty, isFinished: total === filled }); } } function initialize() { const elements = Array.from( body.querySelectorAll('input[required], select[required], textarea[required]') ).filter(isElementVisible); elements.forEach(el => { updateRequiredState(el); el.addEventListener('input', () => updateRequiredState(el)); el.addEventListener('change', () => updateRequiredState(el)); }); updateRequiredProgress(); } // 🔥 Reagiere auf Sichtbarkeitsänderungen const observer = new MutationObserver(updateRequiredProgress); observer.observe(body, { attributes: true, subtree: true, attributeFilter: ['style', 'class', 'hidden'] }); initialize(); // Optional: API zurückgeben return { initialize: initialize, refresh: updateRequiredProgress, destroy() { observer.disconnect(); } }; }