Files
2026-05-23 21:31:34 +02:00

156 lines
4.5 KiB
JavaScript

(function () {
"use strict";
var cfg = window.AZA_DOC;
if (!cfg) return;
var editor = document.getElementById("doc-editor");
var titleEl = document.getElementById("doc-title");
var categoryEl = document.getElementById("doc-category");
var taskEl = document.getElementById("doc-task");
var statusEl = document.getElementById("save-status");
var saveBtn = document.getElementById("btn-save");
var saving = false;
var autoTimer = null;
var lastSaved = "";
function setStatus(state, text) {
statusEl.className = "save-status save-status-" + state;
statusEl.textContent = text;
}
function payloadSnapshot() {
return JSON.stringify({
title: titleEl.value,
category: categoryEl.value,
task: taskEl.value,
html: editor.innerHTML,
});
}
function markDirty() {
if (!saving) {
setStatus("unsaved", "Nicht gespeicherte Änderungen");
}
clearTimeout(autoTimer);
autoTimer = setTimeout(function () {
saveDocument(false);
}, 3000);
}
function saveDocument(manual) {
if (saving) return;
var snap = payloadSnapshot();
if (!manual && snap === lastSaved) {
setStatus("saved", "Gespeichert");
return;
}
saving = true;
setStatus("saving", "Speichert...");
var fd = new FormData();
fd.append("csrf_token", cfg.csrf);
fd.append("title", titleEl.value.trim() || "Unbenanntes Dokument");
fd.append("content_html", editor.innerHTML);
fd.append("category", categoryEl.value);
fd.append("task_id", taskEl.value);
fetch("/api/documents/" + cfg.id + "/save", {
method: "POST",
body: fd,
credentials: "same-origin",
})
.then(function (r) { return r.json(); })
.then(function (data) {
saving = false;
if (data.ok) {
lastSaved = snap;
setStatus("saved", "Gespeichert");
} else {
setStatus("error", "Fehler beim Speichern");
}
})
.catch(function () {
saving = false;
setStatus("error", "Fehler beim Speichern");
});
}
function findListItem(node) {
var el = node && node.nodeType === 3 ? node.parentElement : node;
while (el && el !== editor) {
if (el.tagName === "LI") return el;
el = el.parentElement;
}
return null;
}
function isEmptyListItem(li) {
if (!li) return false;
var text = (li.textContent || "").replace(/\u00a0/g, " ").replace(/\u200B/g, "").trim();
return text === "";
}
editor.addEventListener("keydown", function (e) {
if (e.key !== "Enter" || e.shiftKey) return;
var li = findListItem(window.getSelection().anchorNode);
if (!li) return;
if (isEmptyListItem(li)) {
e.preventDefault();
document.execCommand("outdent");
if (findListItem(window.getSelection().anchorNode) && isEmptyListItem(findListItem(window.getSelection().anchorNode))) {
document.execCommand("outdent");
}
var p = document.createElement("p");
p.appendChild(document.createElement("br"));
var parent = li.parentElement;
if (parent && (parent.tagName === "UL" || parent.tagName === "OL") && parent.children.length === 1) {
parent.replaceWith(p);
} else {
li.replaceWith(p);
}
var sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(p);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
markDirty();
}
});
[titleEl, categoryEl, taskEl].forEach(function (el) {
el.addEventListener("input", markDirty);
el.addEventListener("change", markDirty);
});
editor.addEventListener("input", markDirty);
saveBtn.addEventListener("click", function () {
clearTimeout(autoTimer);
saveDocument(true);
});
document.querySelectorAll(".doc-tb-btn").forEach(function (btn) {
btn.addEventListener("click", function (e) {
e.preventDefault();
var cmd = btn.getAttribute("data-cmd");
var val = btn.getAttribute("data-value");
editor.focus();
if (cmd === "link") {
var url = window.prompt("Link-URL (https://...):", "https://");
if (url && !url.toLowerCase().startsWith("javascript:")) {
document.execCommand("createLink", false, url);
}
} else if (cmd === "formatBlock" && val) {
document.execCommand(cmd, false, val);
} else {
document.execCommand(cmd, false, null);
}
markDirty();
});
});
lastSaved = payloadSnapshot();
})();