Files
VITEC-website/packages/vitec/Resources/Public/Javascript/og-image-preview.js
2026-05-29 11:14:02 +02:00

174 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* OG Image Backend Module live preview via AJAX
* EXT:vitec/Resources/Public/Javascript/og-image-preview.js
*/
(function () {
'use strict';
/** Debounce helper */
function debounce(fn, ms) {
let t;
return function (...args) {
clearTimeout(t);
t = setTimeout(() => fn.apply(this, args), ms);
};
}
/** Collect all form values into a FormData-compatible plain object */
function collectFormData() {
const form = document.getElementById('vitecOgForm');
if (!form) return {};
const fd = new FormData(form);
const out = {};
for (const [key, val] of fd.entries()) {
// key looks like "ogimage[something]"
const match = key.match(/^ogimage\[(.+)]$/);
if (match) {
out[key] = val;
}
}
return out;
}
/** POST to the preview endpoint, update the <img> */
async function requestPreview() {
const form = document.getElementById('vitecOgForm');
const spinner = document.getElementById('previewSpinner');
const img = document.getElementById('ogPreviewImg');
const placeholder = document.getElementById('ogPreviewPlaceholder');
const dl = document.getElementById('previewDownload');
if (!form) return;
if (spinner) spinner.classList.remove('d-none');
try {
const body = new URLSearchParams(collectFormData());
const previewUrl = form.dataset.previewUrl || window.location.href;
const resp = await fetch(previewUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString(),
});
if (!resp.ok) throw new Error('Server error ' + resp.status);
const json = await resp.json();
if (json.success && json.dataUri) {
img.src = json.dataUri;
img.style.display = 'block';
if (placeholder) placeholder.style.display = 'none';
if (dl) {
dl.href = json.dataUri;
dl.classList.remove('d-none');
}
} else {
console.warn('[OG Preview]', json.message);
}
} catch (e) {
console.error('[OG Preview] fetch failed:', e);
} finally {
if (spinner) spinner.classList.add('d-none');
}
}
const debouncedPreview = debounce(requestPreview, 600);
// ── Wire up events once DOM is ready ──────────────────────────────
document.addEventListener('DOMContentLoaded', function () {
// Manual preview button
const btn = document.getElementById('btnPreview');
if (btn) {
btn.addEventListener('click', requestPreview);
}
// Auto-preview on any .js-live input change
document.querySelectorAll('.js-live').forEach(function (el) {
el.addEventListener('input', debouncedPreview);
el.addEventListener('change', debouncedPreview);
});
// Background type toggle (show colour vs image picker)
function syncBgType() {
const colorWrap = document.getElementById('bg-color-wrap');
const imageWrap = document.getElementById('bg-image-wrap');
const selected = document.querySelector('input.js-bg-type:checked');
if (!selected) return;
if (selected.value === 'image') {
colorWrap && (colorWrap.style.display = 'none');
imageWrap && (imageWrap.style.display = 'block');
} else {
colorWrap && (colorWrap.style.display = 'block');
imageWrap && (imageWrap.style.display = 'none');
}
}
document.querySelectorAll('input.js-bg-type').forEach(function (el) {
el.addEventListener('change', function () {
syncBgType();
debouncedPreview();
});
});
const bgImageSelect = document.querySelector('select[name="ogimage[bg_image]"]');
if (bgImageSelect) {
bgImageSelect.addEventListener('change', function () {
const imageTypeRadio = document.querySelector('input.js-bg-type[value="image"]');
if (imageTypeRadio) {
imageTypeRadio.checked = true;
}
syncBgType();
requestPreview();
});
}
syncBgType(); // initialise on load
// Hex text ↔ colour picker sync
document.querySelectorAll('.js-hex-sync').forEach(function (hexInput) {
const targetId = hexInput.dataset.target;
const picker = document.getElementById(targetId);
if (!picker) return;
picker.addEventListener('input', function () {
hexInput.value = picker.value;
});
hexInput.addEventListener('input', function () {
const val = hexInput.value.trim();
if (/^#[0-9a-fA-F]{6}$/.test(val)) {
picker.value = val;
picker.dispatchEvent(new Event('input', { bubbles: true }));
}
});
});
// Preset buttons
document.querySelectorAll('.js-preset').forEach(function (btn) {
btn.addEventListener('click', function () {
const bg = btn.dataset.bg;
const tc = btn.dataset.titleColor;
const sc = btn.dataset.subtitleColor;
const bgInput = document.getElementById('bgColor');
if (bgInput && bg) { bgInput.value = bg; bgInput.dispatchEvent(new Event('input', {bubbles:true})); }
const tInput = document.getElementById('titleColor');
if (tInput && tc) { tInput.value = tc; tInput.dispatchEvent(new Event('input', {bubbles:true})); }
const sInput = document.getElementById('subtitleColor');
if (sInput && sc) { sInput.value = sc; sInput.dispatchEvent(new Event('input', {bubbles:true})); }
debouncedPreview();
});
});
});
})();