Files
radixOS/public/javascript/requiredFields.js
2026-04-22 18:13:16 +02:00

92 lines
2.8 KiB
JavaScript

function createRequiredProgress({ container, initOnStartup = true, 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']
});
if(initOnStartup) {
initialize();
}
// Optional: API zurückgeben
return {
initialize: initialize,
refresh: updateRequiredProgress,
destroy() {
observer.disconnect();
}
};
}