This commit is contained in:
@@ -325,6 +325,15 @@ $sectionLinks = [
|
|||||||
</button>
|
</button>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="avatar-loader" data-avatar-loader hidden>
|
||||||
|
<div class="avatar-loader__bar">
|
||||||
|
<span class="avatar-loader__fill" data-avatar-loader-fill style="width:0%"></span>
|
||||||
|
</div>
|
||||||
|
<div class="avatar-loader__meta">
|
||||||
|
<strong data-avatar-loader-label>Varianten werden geladen</strong>
|
||||||
|
<span class="muted small" data-avatar-loader-progress>0%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="avatar-component-panels">
|
<div class="avatar-component-panels">
|
||||||
<?php foreach (\App\Avatar\Lorelei::componentDefinitions() as $field => $meta): ?>
|
<?php foreach (\App\Avatar\Lorelei::componentDefinitions() as $field => $meta): ?>
|
||||||
<section class="avatar-component-panel avatar-component-panel--<?= htmlspecialchars(str_replace(['avatar_lorelei_', '_variant'], '', (string)$field), ENT_QUOTES) ?> <?= $field === 'avatar_lorelei_eyes_variant' ? 'is-active' : '' ?>" data-avatar-component-panel="<?= htmlspecialchars((string)$field, ENT_QUOTES) ?>">
|
<section class="avatar-component-panel avatar-component-panel--<?= htmlspecialchars(str_replace(['avatar_lorelei_', '_variant'], '', (string)$field), ENT_QUOTES) ?> <?= $field === 'avatar_lorelei_eyes_variant' ? 'is-active' : '' ?>" data-avatar-component-panel="<?= htmlspecialchars((string)$field, ENT_QUOTES) ?>">
|
||||||
|
|||||||
@@ -252,6 +252,10 @@ body {
|
|||||||
.avatar-component-nav { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
|
.avatar-component-nav { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
|
||||||
.avatar-component-nav__button { border: 1px solid var(--color-border); background: #fff; color: var(--color-text); border-radius: 999px; padding: 8px 12px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
|
.avatar-component-nav__button { border: 1px solid var(--color-border); background: #fff; color: var(--color-text); border-radius: 999px; padding: 8px 12px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; }
|
||||||
.avatar-component-nav__button.is-active { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); }
|
.avatar-component-nav__button.is-active { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); }
|
||||||
|
.avatar-loader { width: 100%; display: grid; gap: 8px; padding: 12px 14px; background: rgba(255,255,255,0.72); border: 1px solid var(--color-border); border-radius: 14px; }
|
||||||
|
.avatar-loader__bar { width: 100%; height: 10px; overflow: hidden; border-radius: 999px; background: #ece2d4; }
|
||||||
|
.avatar-loader__fill { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, #37485a, #68819a); transition: width 180ms ease; }
|
||||||
|
.avatar-loader__meta { display: flex; justify-content: space-between; gap: 10px; align-items: center; }
|
||||||
.avatar-component-panels { width: 100%; display: grid; }
|
.avatar-component-panels { width: 100%; display: grid; }
|
||||||
.avatar-component-panel { display: none; width: 100%; gap: 10px; }
|
.avatar-component-panel { display: none; width: 100%; gap: 10px; }
|
||||||
.avatar-component-panel.is-active { display: grid; }
|
.avatar-component-panel.is-active { display: grid; }
|
||||||
|
|||||||
@@ -793,19 +793,81 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
return activeTab?.getAttribute('data-avatar-component-tab') || 'avatar_lorelei_eyes_variant';
|
return activeTab?.getAttribute('data-avatar-component-tab') || 'avatar_lorelei_eyes_variant';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setAvatarLoaderState = (form, active, loaded = 0, total = 0, label = 'Varianten werden geladen') => {
|
||||||
|
const loader = form.querySelector('[data-avatar-loader]');
|
||||||
|
const fill = form.querySelector('[data-avatar-loader-fill]');
|
||||||
|
const progress = form.querySelector('[data-avatar-loader-progress]');
|
||||||
|
const labelNode = form.querySelector('[data-avatar-loader-label]');
|
||||||
|
if (!loader || !fill || !progress || !labelNode) return;
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
loader.hidden = true;
|
||||||
|
fill.style.width = '0%';
|
||||||
|
progress.textContent = '0%';
|
||||||
|
labelNode.textContent = label;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const percent = total > 0 ? Math.max(0, Math.min(100, Math.round((loaded / total) * 100))) : 0;
|
||||||
|
loader.hidden = false;
|
||||||
|
fill.style.width = `${percent}%`;
|
||||||
|
progress.textContent = `${percent}%`;
|
||||||
|
labelNode.textContent = label;
|
||||||
|
};
|
||||||
|
|
||||||
const updateAvatarOptionPreviews = (form, activeField = null) => {
|
const updateAvatarOptionPreviews = (form, activeField = null) => {
|
||||||
const selector = activeField
|
const selector = activeField
|
||||||
? `[data-avatar-component-panel="${activeField}"] [data-avatar-option-thumb]`
|
? `[data-avatar-component-panel="${activeField}"] [data-avatar-option-thumb]`
|
||||||
: '[data-avatar-option-thumb]';
|
: '[data-avatar-option-thumb]';
|
||||||
|
|
||||||
form.querySelectorAll(selector).forEach((image) => {
|
const images = Array.from(form.querySelectorAll(selector));
|
||||||
|
if (!images.length) {
|
||||||
|
setAvatarLoaderState(form, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let loaded = 0;
|
||||||
|
const label = activeField
|
||||||
|
? `Varianten fuer ${form.querySelector(`[data-avatar-component-tab="${activeField}"]`)?.textContent?.trim() || 'diesen Bereich'}`
|
||||||
|
: 'Varianten werden geladen';
|
||||||
|
setAvatarLoaderState(form, true, 0, images.length, label);
|
||||||
|
|
||||||
|
images.forEach((image) => {
|
||||||
const field = image.getAttribute('data-avatar-option-field') || '';
|
const field = image.getAttribute('data-avatar-option-field') || '';
|
||||||
const value = image.getAttribute('data-avatar-option-value') || '';
|
const value = image.getAttribute('data-avatar-option-value') || '';
|
||||||
const params = buildAvatarParams(form, { [field]: value });
|
const params = buildAvatarParams(form, { [field]: value });
|
||||||
if (!params) return;
|
if (!params) {
|
||||||
|
loaded += 1;
|
||||||
|
setAvatarLoaderState(form, true, loaded, images.length, label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
image.dataset.avatarLoaded = 'true';
|
const src = `${avatarEndpoint}?${params.toString()}`;
|
||||||
image.src = `${avatarEndpoint}?${params.toString()}`;
|
if (image.dataset.avatarLoadedSrc === src) {
|
||||||
|
loaded += 1;
|
||||||
|
setAvatarLoaderState(form, true, loaded, images.length, label);
|
||||||
|
if (loaded >= images.length) {
|
||||||
|
window.setTimeout(() => setAvatarLoaderState(form, false), 180);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const preload = new Image();
|
||||||
|
const finalize = () => {
|
||||||
|
loaded += 1;
|
||||||
|
setAvatarLoaderState(form, true, loaded, images.length, label);
|
||||||
|
if (loaded >= images.length) {
|
||||||
|
window.setTimeout(() => setAvatarLoaderState(form, false), 180);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
preload.onload = () => {
|
||||||
|
image.src = src;
|
||||||
|
image.dataset.avatarLoadedSrc = src;
|
||||||
|
finalize();
|
||||||
|
};
|
||||||
|
preload.onerror = finalize;
|
||||||
|
preload.src = src;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -880,7 +942,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
form.querySelectorAll('[data-avatar-component-tab]').forEach((button) => {
|
form.querySelectorAll('[data-avatar-component-tab]').forEach((button) => {
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
const field = button.getAttribute('data-avatar-component-tab');
|
const field = button.getAttribute('data-avatar-component-tab');
|
||||||
if (field) setActiveComponentPanel(field);
|
if (field) {
|
||||||
|
ensureAvatarBuilderLoaded(form);
|
||||||
|
setActiveComponentPanel(field);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -939,6 +1004,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
ensureAvatarBuilderLoaded(form);
|
ensureAvatarBuilderLoaded(form);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('[data-modal-open="modalAvatar"]').forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
const form = document.querySelector('#modalAvatar [data-avatar-builder]');
|
||||||
|
if (!form) return;
|
||||||
|
window.setTimeout(() => ensureAvatarBuilderLoaded(form), 20);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
document.querySelectorAll('[data-nav-events]').forEach(link => {
|
document.querySelectorAll('[data-nav-events]').forEach(link => {
|
||||||
link.addEventListener('click', async () => {
|
link.addEventListener('click', async () => {
|
||||||
if (window.location.pathname === '/' && window.location.hash === '#events') {
|
if (window.location.pathname === '/' && window.location.hash === '#events') {
|
||||||
|
|||||||
Reference in New Issue
Block a user