Zwischenstand vom 29.05.2026
This commit is contained in:
1 parent
b6d2142214
commit
dba154e572
36 files changed
+5113
-649
No files matched your search
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16">
|
||||
<rect x="1.5" y="2.5" width="13" height="11" rx="1" fill="none" stroke="#000" stroke-width="1.2"/>
|
||||
<rect x="3.5" y="4.5" width="9" height="2.2" rx="0.3" fill="#000" opacity="0.55"/>
|
||||
<rect x="3.5" y="7.6" width="9" height="2.2" rx="0.3" fill="#000" opacity="0.35"/>
|
||||
<rect x="3.5" y="10.7" width="9" height="1.6" rx="0.3" fill="#000" opacity="0.2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 447 B |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none">
|
||||
<rect x="1" y="3" width="14" height="10" rx="1.5" fill="#e63946"/>
|
||||
<rect x="1" y="3" width="14" height="10" rx="1.5" stroke="#c1121f" stroke-width="0.5"/>
|
||||
<text x="2" y="10.5" font-size="4.5" font-family="sans-serif" fill="#fff" font-weight="bold">OG</text>
|
||||
<circle cx="11.5" cy="6.5" r="2" fill="#fff" opacity="0.9"/>
|
||||
<polyline points="1,11 5,7 8,9.5 11,6 15,10" stroke="#fff" stroke-width="1" fill="none" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 523 B |
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* 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();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
Reference in new issue
Block a user