Files
webprogrammierung/js/editor.js
T
niklas.ortmann 80f92a384e erweiterter Beitragseditor
content ist nun im json-Format
Bilder können hochgeladen werden
Textblöcke können im Editor angehangen werden
2026-06-14 10:44:17 +02:00

120 lines
4.4 KiB
JavaScript

/**
* Editor-Steuerung für dynamische Inhaltsblöcke
*/
document.addEventListener("DOMContentLoaded", function() {
const form = document.getElementById("editor-form");
// Falls das Formular auf der aktuellen Seite nicht existiert, Skript abbrechen
if (!form) {
return;
}
const container = document.getElementById("block-container");
const plusButton = document.getElementById("plus-button");
const popup = document.getElementById("block-popup");
const hiddenContentInput = document.getElementById("content");
// Pop-up umschalten bei Klick auf das Plus
plusButton.addEventListener("click", () => {
popup.classList.toggle("hidden");
});
// Klick auf eine Block-Option im Pop-up
popup.querySelectorAll("button").forEach(btn => {
btn.addEventListener("click", function() {
const type = this.getAttribute("data-type");
addBlockElement(type, "");
popup.classList.add("hidden");
});
});
// Erstellt ein visuelles HTML-Element im Editor
function addBlockElement(type, value = "") {
const blockDiv = document.createElement("div");
blockDiv.classList.add("editor-block");
blockDiv.setAttribute("data-type", type);
// Löschen-Button für den Block
const deleteBtn = document.createElement("button");
deleteBtn.type = "button";
deleteBtn.innerHTML = "✕";
deleteBtn.classList.add("delete-block-btn");
deleteBtn.addEventListener("click", () => {
blockDiv.remove();
});
blockDiv.appendChild(deleteBtn);
if (type === "text") {
const textarea = document.createElement("textarea");
textarea.placeholder = "Schreibe deinen Textblock...";
textarea.value = value;
blockDiv.appendChild(textarea);
} else if (type === "image") {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = "image/*";
const imgPreview = document.createElement("img");
imgPreview.style.maxWidth = "200px";
imgPreview.style.display = "block";
imgPreview.style.marginTop = "10px";
// Falls bereits ein Bildpfad existiert (z.B. nach einem Reload bei Validierungsfehlern)
if (value && typeof value === 'string' && value.startsWith('uploads/')) {
imgPreview.src = value;
blockDiv.setAttribute("data-value", value);
}
fileInput.addEventListener("change", function() {
if (this.files && this.files[0]) {
const reader = new FileReader();
reader.onload = function(e) {
imgPreview.src = e.target.result;
// Temporäre Speicherung des Base64-Strings im HTML-Attribut
blockDiv.setAttribute("data-value", e.target.result);
}
reader.readAsDataURL(this.files[0]);
}
});
blockDiv.appendChild(fileInput);
blockDiv.appendChild(imgPreview);
}
container.appendChild(blockDiv);
}
// Beim Abschicken: HTML-Blöcke auslesen und als JSON-String serialisieren
form.addEventListener("submit", function(e) {
const blocks = [];
container.querySelectorAll(".editor-block").forEach(blockDiv => {
const type = blockDiv.getAttribute("data-type");
let value = "";
if (type === "text") {
value = blockDiv.querySelector("textarea").value;
} else if (type === "image") {
value = blockDiv.getAttribute("data-value") || "";
}
blocks.push({ type: type, value: value });
});
// JSON-Daten in das unsichtbare Formularfeld schreiben
hiddenContentInput.value = JSON.stringify(blocks);
});
// Existierende Blöcke laden (stellt alte Daten aus der Session wieder her)
try {
const initialBlocks = JSON.parse(hiddenContentInput.value);
if (Array.isArray(initialBlocks)) {
initialBlocks.forEach(b => addBlockElement(b.type, b.value));
}
} catch(e) {
// Fallback für alten Reintext aus Altbeständen
if (hiddenContentInput.value.trim() !== "") {
addBlockElement("text", hiddenContentInput.value);
}
}
});