document.addEventListener("DOMContentLoaded", () => { let data = { // Default current: "", pages: [ {body: "It was a dark and stormy night.\n\nAll was quiet.", choices: [[1,"Continue"]], paths: []}, {body: "Or was it...?", choices: [], paths: ["1"]} ], paths: {"":0, "1":1} }; let state = { editing: false, saveinterval: 0, addcount: 0, path: "" }; const db = new Dexie("vanguard-editor"); db.version(1).stores({files:"name"}); db.on("populate", () => db.files.add({name: "main", data})); db.files.get("main").then(d => { data = d.data; location.hash = "#/"+data.current; state.path = renderPath(); setTimeout(() => document.documentElement.scrollTop = document.getElementById("main").lastChild.offsetTop); }).catch(e => console.error); function download(a, text, name, type) { const file = new Blob([text], {type: type}); a.href = URL.createObjectURL(file); a.download = name; } const prettyDate = d => d.getFullYear() + (d.getMonth()+1).toString().padStart(2, "0") + d.getDate().toString().padStart(2, "0") + "-" + d.getHours().toString().padStart(2, "0") + d.getMinutes().toString().padStart(2, "0") + d.getSeconds().toString().padStart(2, "0"); document.getElementById("save").addEventListener("mouseover", e => { download(e.target, JSON.stringify(data), `Vanguard-${prettyDate(new Date())}.json`, "application/json"); }); document.getElementById("open-file").addEventListener("change", e => { const r = new FileReader(); r.onload = () => { try { data = JSON.parse(r.result); db.files.put({name:"main",data}); location.hash = "#/"+data.current; state.path = renderPath(); setTimeout(() => document.documentElement.scrollTop = document.getElementById("main").lastChild.offsetTop); } catch(e) { alert(e); }}; r.readAsText(e.target.files[0]); }); const viewtpl = document.getElementById("view-entry").content; const edittpl = document.getElementById("edit-entry").content; const choicetpl = document.getElementById("edit-choice").content; function renderView(path, choice) { const pageid = data.paths[path]; const page = data.pages[pageid]; const e = document.createElement("section"); e.appendChild(viewtpl.cloneNode(true)); e.querySelector("a").href = path? `#/${path}/edit` : "#/edit"; e.querySelector("h2").innerHTML = path? (page.paths.length? `#${pageid} / ` + page.paths.map(p => `${p}`).join(" / ") : "UNREACHABLE") : "Start"; e.innerHTML += markup(page.body); if (!page.choices.length) e.innerHTML += "
"; else if (choice) e.innerHTML += `${markup(page.choices[choice-1][1])}`; else e.innerHTML += page.choices.map((c,i) => `${markup(c[1])}`).join(""); return e; } function renderEdit(path) { const pageid = data.paths[path]; const page = data.pages[pageid]; const e = document.createElement("section"); e.appendChild(edittpl.cloneNode(true)); e.classList.add("editing"); e.querySelector("a").href = `#/${path}`; e.querySelector("h2").innerHTML = path? (page.paths.length? `#${pageid} / ` + page.paths.map(p => `${p}`).join(" / ") : "UNREACHABLE") : "Start"; e.querySelector("textarea").value = page.body; page.choices.forEach(c => { const l = document.createElement("div"); l.appendChild(choicetpl.cloneNode(true)); l.classList.add("choice"); l.querySelector("textarea").value = `#${c[0]}: ${c[1]}`; l.querySelector(".choice-delete").addEventListener("click", () => l.parentNode.removeChild(l)); e.querySelector(".choices").appendChild(l); }); e.querySelector(".add-choice").addEventListener("click", () => { const l = document.createElement("div"); l.appendChild(choicetpl.cloneNode(true)); l.classList.add("choice"); const t = l.querySelector("textarea"); t.value = `#${data.pages.length + (state.addcount++)}: Choice text...`; window.addEventListener("resize", () => resizeTA(t)); t.addEventListener("input", () => resizeTA(t)); l.querySelector(".choice-delete").addEventListener("click", () => l.parentNode.removeChild(l)); e.querySelector(".choices").appendChild(l); resizeTA(t); t.focus(); }); return e; }; function resizeTA(e) { const c = e.parentNode; c.style.height = c.scrollHeight + "px"; e.style.height = ""; e.style.height = e.scrollHeight + "px"; c.style.height = ""; } function renderPath() { let path = location.hash.slice(2); const main = document.getElementById("main"); const o = main.cloneNode(false); state.addcount = 0; state.editing = path.endsWith("edit"); if (state.editing) path = path.slice(0,-5); if (!/[0-9]+(-[0-9]+)*/.test(path)) path = ""; const pieces = path.split("-"); if (pieces[0]) for (let i=0; i