Přeskočit na obsah

Živý náhled v adminu

Aby admin uměl živý náhled (změny z editoru hned v iframu, bez rebuildu), web musí mít PreviewBridge skript + markery na editovatelných prvcích. Funguje i cross-origin (admin contenta.cz načte tvou doménu).

MarkerPoužití
data-cn="hero.title"textContent z cesty v site-config (homepage/hlavička/patička)
data-cn-html="…"innerHTML (rich-text v landingu)
data-cn-field="title"textContent pole na detailu (článek/pojem) — title, perex
data-cn-html="body"innerHTML těla na detailu
data-cn-src="cover"atribut src obrázku na detailu

URL flagy: homepage ?preview=1&cnpreview=1, detaily ?cnpreview=1. Pole u detailu posílá admin jako { title, perex, body, cover }.

Vlož jako <script is:inline> do layoutu. Aktivní jen v iframu adminu s ?cnpreview=1:

(function () {
if (window === window.parent) return; // jen v iframu
if (new URLSearchParams(location.search).get("cnpreview") !== "1") return;
function allowed(o) {
return /^https?:\/\/localhost(:\d+)?$/.test(o) || /^https?:\/\/([a-z0-9-]+\.)*contenta\.cz$/.test(o);
}
function get(o, p) { return p.split(".").reduce((a, k) => (a == null ? undefined : a[k]), o); }
function patchText(L) {
document.querySelectorAll("[data-cn]").forEach((el) => {
const v = get(L, el.getAttribute("data-cn"));
if (typeof v === "string" || typeof v === "number") el.textContent = String(v);
});
}
function patchFields(f) {
document.querySelectorAll("[data-cn-field]").forEach((el) => {
const v = f[el.getAttribute("data-cn-field")];
if (typeof v === "string" || typeof v === "number") el.textContent = String(v);
});
document.querySelectorAll("[data-cn-html]").forEach((el) => {
const v = f[el.getAttribute("data-cn-html")]; if (typeof v === "string") el.innerHTML = v;
});
document.querySelectorAll("[data-cn-src]").forEach((el) => {
const v = f[el.getAttribute("data-cn-src")]; if (typeof v === "string" && v) el.setAttribute("src", v);
});
}
window.addEventListener("message", (e) => {
if (!allowed(e.origin)) return;
const d = e.data; if (!d || d.source !== "contenta-admin") return;
if (d.type === "preview") patchText(d.landing || {});
else if (d.type === "preview-fields") patchFields(d.fields || {});
});
try { window.parent.postMessage({ source: "contenta-preview", type: "ready" }, "*"); } catch (e) {}
})();