Button to load character saves plus a little warning about data loss

This commit is contained in:
Eric Fredricksen
2023-12-11 22:37:11 -08:00
committed by Eric Fredricksen
parent b1fa424302
commit 0286ac1338
2 changed files with 163 additions and 110 deletions
+44 -8
View File
@@ -13,10 +13,16 @@
.brag { .brag {
display: inline-block; display: inline-block;
}
.brag, #buttonline td {
background-color: #ddddff; background-color: #ddddff;
margin: 5px; margin: 5px;
border: solid 2px #ccccee; border: solid 2px #ccccee;
} }
.bragtable {
display: inline-block;
border-spacing: 20px;
}
.lit { .lit {
border: solid 2px #66ccee; border: solid 2px #66ccee;
} }
@@ -49,6 +55,7 @@ p {
#newc { #newc {
text-align: center; text-align: center;
} }
.brag a, .brag a:visited { .brag a, .brag a:visited {
color: blue; color: blue;
text-decoration: none; text-decoration: none;
@@ -77,11 +84,30 @@ a.save {
img { img {
border-style: none; border-style: none;
} }
#dropinfo { .dropinfo {
text-align: center; text-align: center;
font-style: italic; font-style: italic;
font-size: smaller; /* font-size: smaller;*/
border: solid 1px #888;
width: 600px;
margin: auto;
margin-bottom: 20px; margin-bottom: 20px;
background-color: #f8f0ee;
border-radius: 0.3rem;
}
.dropinfo div {
margin: 20px;
}
label {
background-color: #f0f0f0;
color: #222;
padding: 2px 6px 2px 6px;
border: solid 1px #888;
font-family: -apple-system, Tahoma, Helvetica, sans-serif;
border-radius: 0.3rem;
cursor: pointer;
font-style: normal;
font-size: 13.33333px;
} }
</style> </style>
</head> </head>
@@ -94,20 +120,30 @@ img {
<h1>Character Roster</h1> <h1>Character Roster</h1>
<p id="roster" class="banter"> <p id="roster" class="banter"></p>
</p>
<table class="brag"> <table class=bragtable>
<tr> <tr id=buttonline>
<td id="newc"> <td id="newc">
<b>New Character</b><br> <b>New Character</b><br>
<img src="dicebar.jpg" alt="four dice"><br> <img src="dicebar.jpg" alt="progress on dice pips"><br>
<button id="roll">Roll One Up</button> <button id="roll">Roll One Up</button>
</td> </td>
</tr> </tr>
</table> </table>
<p id=dropinfo>You can also drop a saved game file on this page to add it to your roster.</p>
<div class=dropinfo>
<div>
Your character data exists only in this browser and will disappear if the browser data is cleared.
You can save a backup by clicking a character's <span style="font-style:normal">&#x1f4be;</span> icon.
To load a saved game in this browser, drop a game save file onto this page, or use this button:
</div><div>
<input id=pickup type=file accept=".pqw" multiple hidden></input>
<label id=uploader for=pickup>Load a Saved Game</label>
</div>
</div>
<div align="center" id="nabar"> <div align="center" id="nabar">
<a href="/">Home</a> &middot; <a href="/">Home</a> &middot;
+119 -102
View File
@@ -1,143 +1,160 @@
function b64_decode(value) { function b64_decode(value) {
return JSON.parse(decodeURIComponent(escape(atob(value)))); return JSON.parse(decodeURIComponent(escape(atob(value))));
} }
function b64_stringify(value) { function b64_stringify(value) {
return btoa(unescape(encodeURIComponent(JSON.stringify(value)))); return btoa(unescape(encodeURIComponent(JSON.stringify(value))));
}
function dropGuy(sheet) {
try {
sheet = sheet.replace(/\s/g, "");
sheet = b64_decode(sheet);
storage.loadRoster(games => {
if (!games[sheet.Traits.Name] ||
confirm(`A character named ${sheet.Traits.Name} already exists. Overwrite it?`)) {
storage.addToRoster(sheet, () => storage.loadRoster(loadGames));
}
});
} catch(err) {
console.log(err);
setTimeout(() => alert("Invalid character data", 1));
}
} }
function load() { function load() {
if (!window.localStorage) { if (!window.localStorage) {
roster.html("<b>Hrumph:</b> This browser does not support local storage. You can still play fast and loose: your character will live only as long as the game stays running in your browser."); roster.html("<b>Hrumph:</b> This browser does not support local storage. You can still play fast and loose: your character will live only as long as the game stays running in your browser.");
return; return;
} }
storage.loadRoster(loadGames); storage.loadRoster(loadGames);
window.addEventListener("dragover", e => { window.addEventListener("dragover", e => {
e.preventDefault(); e.preventDefault();
e.dataTransfer.dropEffect = "copy"; e.dataTransfer.dropEffect = "copy";
}); });
window.addEventListener("drop", e => { window.addEventListener("drop", e => {
e.preventDefault(); e.preventDefault();
e.stopImmediatePropagation(); e.stopImmediatePropagation();
let files = e.dataTransfer.files; let files = e.dataTransfer.files;
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
files[i].text().then(sheet => { files[i].text().then(dropGuy);
try { }
sheet = sheet.replace(/\s/g, ""); });
sheet = b64_decode(sheet);
storage.loadRoster(games => {
if (!games[sheet.Traits.Name] ||
confirm(`A character named ${sheet.Traits.Name} already exists. Overwrite it?`)) {
storage.addToRoster(sheet, () => storage.loadRoster(loadGames));
}
});
} catch(err) {
console.log(err);
setTimeout(() => alert("Invalid character data", 1));
}
});
}
});
document.getElementById('pickup').addEventListener('change', e => {
for (const file of e.target.files) {
console.log(file);
var reader = new FileReader();
reader.readAsText(file, "UTF-8");
reader.onload = function (evt) {
dropGuy(evt.target.result);
}
reader.onerror = function (evt) {
console.log("error reading file");
}
}
e.target.value = '';
});
} }
function loadGames(games) { function loadGames(games) {
var roster = $("#roster"); var roster = $("#roster");
roster.empty(); roster.empty();
var newone = window.location.href.split('#')[1]; var newone = window.location.href.split('#')[1];
var count = 0; var count = 0;
$.each(games, function (key, c) { $.each(games, function (key, c) {
var name = c.Traits.Name; var name = c.Traits.Name;
var br = brag(c); var br = brag(c);
roster.append(br); roster.append(br);
br.find("a.go").attr("href", "main.html#" + escape(name)); br.find("a.go").attr("href", "main.html#" + escape(name));
br.find("a.x").click(function () { br.find("a.x").click(function () {
if (confirm("Terminate " + Pick(["faithful","noble","loyal","brave"])+ if (confirm("Terminate " + Pick(["faithful","noble","loyal","brave"])+
" " + name + "?")) { " " + name + "?")) {
delete games[name]; delete games[name];
storage.storeRoster(games); storage.storeRoster(games);
load(); load();
} }
}); });
br.find("a.sheet").click(function () { br.find("a.sheet").click(function () {
alert(template($("#sheet").html(), games[name])); alert(template($("#sheet").html(), games[name]));
// TODO: put in a window or whatev // TODO: put in a window or whatev
}); });
br.find("a.save").attr("href", br.find("a.save").attr("href",
`data:text/plain;name=${name}.pqw,${b64_stringify(c)}`); `data:text/plain;name=${name}.pqw,${b64_stringify(c)}`);
br.find("a.save").attr("download", `${name}.pqw`); br.find("a.save").attr("download", `${name}.pqw`);
if (name === newone) if (name === newone)
br.addClass("lit"); br.addClass("lit");
br.click(e => { br.click(e => {
if (e.altKey) { if (e.altKey) {
let text = b64_stringify(c); let text = b64_stringify(c);
text = text.match(/.{1,80}/g).join('\n'); text = text.match(/.{1,80}/g).join('\n');
$("dialog#copy pre").text(text); $("dialog#copy pre").text(text);
$("dialog#copy span").text(name); $("dialog#copy span").text(name);
sel = window.getSelection(); sel = window.getSelection();
window.setTimeout(() => { window.setTimeout(() => {
let range = document.createRange(); let range = document.createRange();
range.selectNodeContents($("dialog#copy pre")[0]); range.selectNodeContents($("dialog#copy pre")[0]);
sel.removeAllRanges(); sel.removeAllRanges();
sel.addRange(range); sel.addRange(range);
}, 1); }, 1);
$("dialog#copy")[0].showModal(); $("dialog#copy")[0].showModal();
// window.prompt("Copy to clipboard", text); // window.prompt("Copy to clipboard", text);
} }
}); });
br.find("a.go").attr("data-downloadurl", `text/plain:${name}.pqw:data:text/plain,${b64_stringify(c)}`); br.find("a.go").attr("data-downloadurl", `text/plain:${name}.pqw:data:text/plain,${b64_stringify(c)}`);
++count; ++count;
}); });
if (!count) if (!count)
roster.html("<i>Games you start can be loaded from this page, but no saved games were found. Roll up a new character to get started.</i>"); roster.html("<i>Games you start can be loaded from this page, but no saved games were found. Roll up a new character to get started.</i>");
} }
function brag(sheet) { function brag(sheet) {
var brag = $(template($("#badge").html(), sheet)); var brag = $(template($("#badge").html(), sheet));
if (sheet.motto) { if (sheet.motto) {
brag.find(".bs").text('"' + sheet.motto + '"'); brag.find(".bs").text('"' + sheet.motto + '"');
} }
if (sheet.online) { if (sheet.online) {
brag.addClass("online"); brag.addClass("online");
brag.find(".bs").text("Realm of " + sheet.online.realm); brag.find(".bs").text("Realm of " + sheet.online.realm);
brag.find(".icon.go").html("&#x273F;"); brag.find(".icon.go").html("&#x273F;");
} }
return brag; return brag;
} }
function clearRoster() { function clearRoster() {
storage.storeRoster({}, load); storage.storeRoster({}, load);
} }
$(document).ready(function () { $(document).ready(function () {
load(); load();
$("#roll").click(function () { $("#roll").click(function () {
window.location = "newguy.html"; window.location = "newguy.html";
}); });
$("#test").click(function () { $("#test").click(function () {
window.location = "newguy.html?sold"; window.location = "newguy.html?sold";
}); });
$("#clear").click(clearRoster); $("#clear").click(clearRoster);
}); });