/* ================================================================ TRTOI 就地編輯(inline editing) 登入後:按「編輯此頁」→ 頁面上的文字直接可改 → 按「儲存」寫回。 每個可編輯元素帶 data-e="JSON 路徑";data-html="1" 者保留 HTML。 ================================================================ */ (function () { "use strict"; var nodes = [].slice.call(document.querySelectorAll("[data-e]")); if (!nodes.length) return; var fab = document.getElementById("editToggle"); var bar = document.getElementById("editbar"); var saveBtn = document.getElementById("saveBtn"); var cancelBtn = document.getElementById("cancelBtn"); var editing = false; var backup = {}; function readVal(n) { return n.getAttribute("data-html") ? n.innerHTML.trim() : n.textContent.trim(); } function writeVal(n, v) { if (n.getAttribute("data-html")) n.innerHTML = v; else n.textContent = v; } function enter() { editing = true; document.body.classList.add("edit-mode"); nodes.forEach(function (n) { backup[n.getAttribute("data-e")] = readVal(n); n.setAttribute("contenteditable", "true"); }); bar.classList.add("show"); fab.style.display = "none"; } function leave() { editing = false; document.body.classList.remove("edit-mode"); nodes.forEach(function (n) { n.removeAttribute("contenteditable"); }); bar.classList.remove("show"); fab.style.display = ""; } // 編輯時避免點到連結就跳走 document.addEventListener("click", function (e) { if (!editing) return; var a = e.target.closest ? e.target.closest("a") : null; if (a) e.preventDefault(); }, true); fab.addEventListener("click", enter); cancelBtn.addEventListener("click", function () { nodes.forEach(function (n) { var k = n.getAttribute("data-e"); if (k in backup) writeVal(n, backup[k]); }); leave(); }); saveBtn.addEventListener("click", function () { // 依目標分頁分組:預設寫回目前頁面(window.SLUG), // 帶 data-slug 者寫回指定目標(如側欄註記 → 站台層級 "site")。 var groups = {}; nodes.forEach(function (n) { var slug = n.getAttribute("data-slug") || window.SLUG; (groups[slug] || (groups[slug] = {}))[n.getAttribute("data-e")] = readVal(n); }); saveBtn.disabled = true; saveBtn.textContent = "儲存中…"; Promise.all(Object.keys(groups).map(function (slug) { return fetch("/admin/save-inline/" + slug, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ patches: groups[slug], lang: window.LANG }) }).then(function (r) { return r.json(); }); })) .then(function (results) { if (results.every(function (res) { return res && res.ok; })) { location.reload(); } else { var bad = results.filter(function (r) { return !(r && r.ok); })[0]; alert("儲存失敗:" + ((bad && bad.error) || "未知錯誤")); saveBtn.disabled = false; saveBtn.textContent = "儲存"; } }) .catch(function () { alert("儲存失敗(無法連線)"); saveBtn.disabled = false; saveBtn.textContent = "儲存"; }); }); })();