diff --git a/js/editor.js b/js/editor.js
index 9d98679..be37ba6 100644
--- a/js/editor.js
+++ b/js/editor.js
@@ -10,10 +10,13 @@ document.title = "Editor|" + deckName;
window.addEventListener("load", () => {
// load deck input json
- getJSON("deck.input.json", json => {
- deckJSON = json;
- makeSVGs(deckJSON);
- });
+ fetch("deck.input.json")
+ .then(data => data.json())
+ .then(json => {
+ deckJSON = json;
+ makeSVGs(deckJSON);
+ })
+ .catch(error => console.error(error));
// deck JSON uploader
document.querySelector('#jsonUpload').addEventListener('change', event => {
@@ -96,55 +99,54 @@ function downloadFile(file, name) {
document.body.removeChild(dl);
}
-function getJSON(filename, callback) {
- let xhr = new XMLHttpRequest();
- xhr.addEventListener("load", () => {
- if (xhr.status === 200) {
- callback(JSON.parse(xhr.responseText));
- }
- });
- xhr.open("GET", filename);
- xhr.send();
-}
-
function getSVGTemplate(name, callback) {
- let xhr = new XMLHttpRequest();
- xhr.addEventListener("load", () => {
- let respSVG = xhr.responseXML.children[0];
- callback(respSVG);
- });
- xhr.open("GET", "/template/" + name + ".svg");
- xhr.send();
+ return fetch("/template/" + name + ".svg")
+ .then(response => response.text())
+ .then(str => (new window.DOMParser()).parseFromString(str, "text/xml").activeElement);
}
-function makeSVGs(deckJSON) {
+async function makeSVGs(deckJSON) {
document.querySelector('#deckName').value = deckJSON.name || "";
document.querySelector('#deckType').value = deckJSON.type || "";
let deck = document.querySelector('#deck');
deck.innerHTML = "";
- setDeckTemplate(deckJSON.type, () => {
- Object.entries(template.cardTypes).forEach(cardType => {
- getSVGTemplate(deckJSON.type + "/" + cardType[0], templateSVG => {
- deck.style.width = Math.ceil(Math.sqrt(deckJSON.deck.length)) *
- parseInt(templateSVG.getAttribute("width")) + "pt";
- deck.style.height = Math.ceil(Math.sqrt(deckJSON.deck.length)) *
- parseInt(templateSVG.getAttribute("height")) + "pt";
+ let template = await fetch(`/template/${deckJSON.type}/input.json`)
+ .then(data => data.json());
- // build card SVGs
- deckJSON[cardType[0]].forEach(
- card => makeCardSVG(deck, cardType[1], templateSVG, card));
- });
+ let cardCount = Object.entries(template.cardTypes)
+ .map(ct => deckJSON[ct[0]].length * (ct[1].back ? 2 : 1))
+ .reduce((sum, current) => sum + current, 0);
+
+ // note: needs to be a for loop because it needs to be synchronous
+ // and also have await
+ // Although I suppose I could prefetch the SVGs and then do the rest...
+ for (let cardType of Object.entries(template.cardTypes)) {
+ let backSVG;
+ if (cardType[1].back) {
+ let backTemplate = cardType[1].back.template || (cardType[0] + "-back");
+ backSVG = await getSVGTemplate(deckJSON.type + "/" + backTemplate);
+ }
+ let templateSVG = await getSVGTemplate(deckJSON.type + "/" + cardType[0]);
+ console.log(templateSVG);
+
+ // build card SVGs
+ deckJSON[cardType[0]].forEach(card => {
+ makeCardSVG(deck, cardType[1], templateSVG, card);
+
+ // if there is a back, build it too
+ if (cardType[1].back) {
+ makeCardSVG(deck, cardType[1].back, backSVG, card, back=true);
+ }
});
- });
-}
-function setDeckTemplate(type, callback) {
- getJSON("/template/" + type + "/input.json", json => {
- template = json;
- callback();
- });
+ // set div width/height based on number of cards
+ deck.style.width = Math.ceil(Math.sqrt(cardCount)) *
+ parseInt(templateSVG.getAttribute("width")) + "pt";
+ deck.style.height = Math.ceil(Math.sqrt(cardCount)) *
+ parseInt(templateSVG.getAttribute("height")) + "pt";
+ };
}
function setForm(cardTemplate, card) {
@@ -170,21 +172,20 @@ function setForm(cardTemplate, card) {
});
}
-function makeCardSVG(deck, cardInputTemplate, templateSVG, card) {
+function makeCardSVG(deck, cardInputTemplate, templateSVG, card, back=false) {
+ let propSource = (back && card.back) ? card.back : card;
let cardSVG = deck.appendChild(templateSVG.cloneNode(true));
cardSVG.addEventListener('click', () => {
selected = {svg: cardSVG, json: card};
setForm(cardInputTemplate, card);
}, true);
- Object.keys(cardInputTemplate.inputs).forEach(
- prop => wrapSVGText(cardSVG.querySelector('#' + prop), String(card[prop] || "")));
- Object.entries(cardInputTemplate.hide).forEach(hidable => {
- if (hidable[1] in card) {
- cardSVG.querySelector('#' + hidable[0]).setAttribute('display', '');
- }
- else {
- cardSVG.querySelector('#' + hidable[0]).setAttribute('display', 'none');
- }
+ Object.keys(cardInputTemplate.inputs).forEach(prop => {
+ let inputProp = propSource[prop] || card[prop] || "";
+ wrapSVGText(cardSVG.querySelector('#' + prop), String(inputProp));
+ });
+ Object.entries(cardInputTemplate.hide || []).forEach(hidable => {
+ cardSVG.querySelector('#' + hidable[0])
+ .setAttribute('display', hidable[1] in propSource ? '' : 'none');
});
}
@@ -193,10 +194,11 @@ function upload() {
// POST the generated SVGs to the server
let data = (new XMLSerializer()).serializeToString(deck);
- let xhr = new XMLHttpRequest();
- xhr.open('POST', "upload");
- xhr.setRequestHeader("Content-Type", "application/json");
- xhr.send(JSON.stringify({body: data, json: deckJSON}));
+ fetch('upload', {
+ method: 'post',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({body: data, json: deckJSON})
+ });
}
function wrapSVGText(e, string) {
diff --git a/server.js b/server.js
index a88fac9..2cd8045 100644
--- a/server.js
+++ b/server.js
@@ -50,12 +50,14 @@ const server = http.createServer((req, res) => {
case "card.json":
case "deck.json":
case "environment/input.json":
+ case "hero/input.json":
+ case "villain/input.json":
sendFile(res, "template/" + item, 'application/json');
break;
case "environment/deck.svg":
case "hero/deck.svg":
case "hero/character-back.svg":
- case "hero/character-front.svg":
+ case "hero/character.svg":
case "villain/deck.svg":
case "villain/character.svg":
case "villain/instructions.svg":
diff --git a/template/environment/input.json b/template/environment/input.json
index a11ea81..1439eb8 100644
--- a/template/environment/input.json
+++ b/template/environment/input.json
@@ -1,6 +1,7 @@
{
"cardTypes": {
"deck": {
+ "meta": ["count"],
"inputs": {
"name": "text",
"keywords": "text",
diff --git a/template/hero/character-back.svg b/template/hero/character-back.svg
index de47764..be5ee60 100644
--- a/template/hero/character-back.svg
+++ b/template/hero/character-back.svg
@@ -4,7 +4,7 @@
-
+
{ Text Here
{ Text Here
{ Text Here
diff --git a/template/hero/character-front.svg b/template/hero/character.svg
similarity index 100%
rename from template/hero/character-front.svg
rename to template/hero/character.svg
diff --git a/template/hero/input.json b/template/hero/input.json
index 664c666..1b83ec4 100644
--- a/template/hero/input.json
+++ b/template/hero/input.json
@@ -1,5 +1,17 @@
{
"cardTypes": {
+ "character": {
+ "back": {
+ "inputs": {
+ "incapacitated": "text"
+ }
+ },
+ "inputs": {
+ "hp": "number",
+ "power": "text",
+ "powerText": "textarea"
+ }
+ },
"deck": {
"inputs": {
"name": "text",
diff --git a/template/villain/input.json b/template/villain/input.json
index 664c666..4d18ced 100644
--- a/template/villain/input.json
+++ b/template/villain/input.json
@@ -1,5 +1,40 @@
{
"cardTypes": {
+ "character": {
+ "back": {
+ "template": "character",
+ "inputs": {
+ "name": "text",
+ "hp": "number",
+ "title": "text"
+ }
+ },
+ "inputs": {
+ "name": "text",
+ "hp": "number",
+ "title": "text"
+ }
+ },
+ "instructions": {
+ "back": {
+ "template": "instructions",
+ "inputs": {
+ "name": "text",
+ "title": "text",
+ "gameplay": "textarea"
+ },
+ "hide": {
+ "setupBox": "setup"
+ }
+ },
+ "inputs": {
+ "name": "text",
+ "title": "text",
+ "setup": "textarea",
+ "gameplay": "textarea",
+ "advanced": "textarea"
+ }
+ },
"deck": {
"inputs": {
"name": "text",
diff --git a/template/villain/instructions.svg b/template/villain/instructions.svg
index e82ea63..b1e552a 100644
--- a/template/villain/instructions.svg
+++ b/template/villain/instructions.svg
@@ -9,16 +9,18 @@
Villain Name
- Villain Title
- Art By
- Text Here
-
-
-
- Text Here
- SetUp
+
+ Villain Title
+
+
+
+ Text Here
+ SetUp
+
+ Game Play
+ Text Here
+ Advanced
+ Text Here
+ Art By
- Game Play
- Advanced
- Text Here