Skip to content

Commit f74c74c

Browse files
committed
Handle compendium tags in a more orderly manner
1 parent 253fb4a commit f74c74c

File tree

3 files changed

+200
-98
lines changed

3 files changed

+200
-98
lines changed

src/spell_compendium.js

Lines changed: 132 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/**
2+
* @typedef {object} SpellData
3+
* @property {string} name
4+
* @property {string} author
5+
* @property {number} tier
6+
* @property {string[]} tags
7+
* @property {string} cost
8+
* @property {string} range
9+
* @property {string} duration
10+
* @property {string} desc
11+
* @property {string} empower
12+
*/
13+
/**
14+
* @var {SpellData[]} SpellDatabase
15+
*/
16+
117
class SpellCompendium {
218
static UI = {
319
LeftDiv: document.getElementById('compendium_left'),
@@ -40,21 +56,27 @@ class SpellCompendium {
4056
School: {},
4157
Forbidden: {},
4258
};
59+
static ProcessedTags = {};
4360
static {
4461
SpellDatabase.forEach( (spell) => {
62+
SpellCompendium.ProcessedTags[spell.name] = [];
4563
spell.tags.forEach( (tag) => {
4664
if (tag.includes('Forbidden')) {
4765
SpellCompendium.TagCounts.Forbidden[tag] ??= 0;
4866
SpellCompendium.TagCounts.Forbidden[tag] ++;
67+
SpellCompendium.ProcessedTags[spell.name].push({ type: 'Forbidden', tag: tag.match(/Forbidden \((.+)\)/)[1] });
4968
} else if (tag in SpellCompendium.TagDescriptions.Functional) {
5069
SpellCompendium.TagCounts.Functional[tag] ??= 0;
5170
SpellCompendium.TagCounts.Functional[tag] ++;
71+
SpellCompendium.ProcessedTags[spell.name].push({ type: 'Functional', tag: tag });
5272
} else if (tag in SpellCompendium.TagDescriptions.School) {
5373
SpellCompendium.TagCounts.School[tag] ??= 0;
5474
SpellCompendium.TagCounts.School[tag] ++;
75+
SpellCompendium.ProcessedTags[spell.name].push({ type: 'School', tag: tag });
5576
} else {
5677
SpellCompendium.TagCounts.Regular[tag] ??= 0;
5778
SpellCompendium.TagCounts.Regular[tag] ++;
79+
SpellCompendium.ProcessedTags[spell.name].push({ type: 'Regular', tag: tag });
5880
}
5981
})
6082
});
@@ -63,10 +85,24 @@ class SpellCompendium {
6385
static tagSelection = new Set();
6486
static tierSelection = new Set();
6587

66-
static tagDescription(tag) {
67-
return SpellCompendium.TagDescriptions.Functional[
68-
Object.keys(SpellCompendium.TagDescriptions.Functional).find(fTag => tag.includes(fTag))
69-
];
88+
// Generate tag description for functional tags
89+
static tagDescription(tag, type) {
90+
if (type === 'Forbidden') {
91+
return SpellCompendium.TagDescriptions.Functional['Forbidden'];
92+
} else if (type === 'Functional') {
93+
return SpellCompendium.TagDescriptions.Functional[tag];
94+
} else {
95+
return '';
96+
}
97+
}
98+
99+
static tagSpan(tag, type) {
100+
const span = document.createElement('span');
101+
const fTag = ['Functional', 'Forbidden'].includes(type);
102+
span.className = fTag ? 'fTag' : '';
103+
span.textContent = (type === 'Forbidden') ? `Forbidden (${tag})` : tag;
104+
span.title = SpellCompendium.tagDescription(tag, type);
105+
return span;
70106
}
71107

72108
// Generate full-sized spell description
@@ -98,10 +134,12 @@ class SpellCompendium {
98134
tagsH.className = 'spellheaders';
99135
tagsD.className = 'spelltags';
100136
tagsH.textContent = 'Tags:';
101-
tagsD.innerHTML = spell.tags
102-
.map(tag => Object.keys(SpellCompendium.TagDescriptions.Functional).some(fTag => tag.includes(fTag)) ? `<span class='fTag' title='${SpellCompendium.tagDescription(tag)}'>${tag}</span>` : tag)
103-
.join(', ')
104-
;
137+
SpellCompendium.ProcessedTags[spell.name].forEach( ({ type, tag }, index) => {
138+
if (index > 0) {
139+
tagsD.appendChild(document.createTextNode(', '));
140+
}
141+
tagsD.appendChild(SpellCompendium.tagSpan(tag, type));
142+
});
105143

106144
const costRow = cardBody.appendChild(document.createElement('tr'));
107145
const costH = costRow.appendChild(document.createElement('td'));
@@ -144,30 +182,49 @@ class SpellCompendium {
144182
return card;
145183
}
146184

185+
static spellDatum(parent, text) {
186+
const datum = parent.appendChild(document.createElement('td'));
187+
datum.className = 'spelldata';
188+
datum.textContent = text;
189+
}
190+
147191
// Generate spell table entry
148192
static spellBrief(spell) {
193+
const processedTags = SpellCompendium.ProcessedTags[spell.name];
194+
149195
const brief = document.createElement('tr');
150196
brief.id = `spell_${spell.name.replaceAll(' ', '_')}`;
197+
brief.classList.add('spellbrief');
198+
processedTags.forEach( ({ type, tag }) => {
199+
if (type == 'Regular') {
200+
brief.classList.add(`tag-${tag}`);
201+
} else if (type == 'Forbidden') {
202+
brief.classList.add(`tag-${type}-${tag}`);
203+
brief.classList.add(`spell-Forbidden`);
204+
} else {
205+
brief.classList.add(`tag-${type}-${tag}`);
206+
}
207+
});
151208

152-
[
153-
spell.name,
154-
spell.tier,
155-
spell.range,
156-
spell.duration,
157-
spell.tags
158-
.map(tag => Object.keys(SpellCompendium.TagDescriptions.Functional).some(fTag => tag.includes(fTag)) ? `<span class='fTag' title='${SpellCompendium.tagDescription(tag)}'>${tag}</span>` : tag)
159-
.join(', ')
160-
].forEach(data => {
161-
const td = brief.appendChild(document.createElement('td'));
162-
td.className = 'spelldata';
163-
td.innerHTML = data;
209+
SpellCompendium.spellDatum(brief, spell.name);
210+
SpellCompendium.spellDatum(brief, spell.tier);
211+
SpellCompendium.spellDatum(brief, spell.range);
212+
SpellCompendium.spellDatum(brief, spell.duration);
213+
214+
const spellTags = brief.appendChild(document.createElement('td'));
215+
spellTags.className = 'spelldata';
216+
processedTags.forEach( ({ type, tag }, index) => {
217+
if (index > 0) {
218+
spellTags.appendChild(document.createTextNode(', '));
219+
}
220+
spellTags.appendChild(SpellCompendium.tagSpan(tag, type));
164221
});
165222

166-
brief.onclick = function() {
167-
const card = SpellCompendium.spellCard(spell, SpellCompendium.TagDescriptions.Functional);
223+
brief.addEventListener('click', function() {
224+
const card = SpellCompendium.spellCard(spell);
168225
const compendiumRight = document.getElementById('compendium_right');
169226
compendiumRight.replaceChild(card, compendiumRight.firstElementChild);
170-
};
227+
});
171228

172229
return brief;
173230
}
@@ -177,10 +234,10 @@ class SpellCompendium {
177234
const oldTable = document.querySelector('#spelltable');
178235
const newTable = oldTable.cloneNode(false);
179236

180-
SpellDatabase.forEach(spell => {
181-
if (SpellCompendium.tagSelection.size > 0 && !spell.tags.some(tag => SpellCompendium.tagSelection.has(tag))) return;
237+
SpellDatabase.forEach( (spell) => {
238+
if (SpellCompendium.tagSelection.size > 0 && !spell.tags.some( (tag) => SpellCompendium.tagSelection.has(tag) )) return;
182239
if (SpellCompendium.tierSelection.size > 0 && !SpellCompendium.tierSelection.has(spell.tier)) return;
183-
newTable.appendChild(SpellCompendium.spellBrief(spell, SpellCompendium.TagDescriptions.Functional));
240+
newTable.appendChild(SpellCompendium.spellBrief(spell));
184241
});
185242

186243
oldTable.parentNode.replaceChild(newTable, oldTable);
@@ -205,27 +262,26 @@ class SpellCompendium {
205262
}
206263

207264
static tagButtons(tags, container) {
208-
Object.entries(tags).sort((a, b) => {
265+
Object.entries(tags).sort( (a, b) => {
209266
if (a[1] == b[1]) {
210267
return (a[0] == b[0]) ? 0 : (a[0] > b[0]) ? 1 : -1;
211268
} else {
212269
return Math.sign(b[1] - a[1]);
213270
}
214-
}).forEach(([tag, count]) => {
271+
}).forEach( ([tag, count]) => {
215272
const div = container.appendChild(document.createElement('button'));
216-
const img = div.appendChild(document.createElement('img'));
273+
div.appendChild(document.createElement('img'));
217274
const text = div.appendChild(document.createElement('div'));
218275

219-
img.width = 14;
220-
img.style.paddingRight = '2px';
221-
222276
text.textContent = `${tag} (${count})`;
223-
text.style.display = 'inline';
224277

225-
div.style.display = 'block';
226-
div.id = `tag_${tag.replaceAll(' ', '_')}`;
227-
if(tag.includes('Forbidden')) div.id = 'tag_Forbidden';
228-
div.className = 'selector';
278+
div.classList.add('selector');
279+
if (tag.includes('Forbidden')) {
280+
div.classList.add('tag-Forbidden');
281+
} else {
282+
div.classList.add(`tag-${tag.replaceAll(' ', '_')}`);
283+
}
284+
229285
div.value = 0;
230286
div.onclick = function() {
231287
const S = parseInt(div.value);
@@ -244,41 +300,57 @@ class SpellCompendium {
244300
});
245301
}
246302

303+
static tierButtonClickHandler(event) {
304+
const tier = parseInt(event.target.dataset.tier);
305+
const state = parseInt(event.target.value);
306+
const maxState = 1;
307+
let newState;
308+
309+
// change state
310+
switch (event.shiftKey) {
311+
// case true:
312+
// newState = state - 1;
313+
// if (newState < 0) newState = maxState;
314+
// break;
315+
default:
316+
newState = state + 1;
317+
if (newState > maxState) newState = 0;
318+
break;
319+
}
320+
event.target.value = newState;
321+
322+
switch (newState) {
323+
case 0:
324+
SpellCompendium.tierSelection.delete(tier);
325+
break;
326+
case 1:
327+
SpellCompendium.tierSelection.add(tier);
328+
break;
329+
}
330+
SpellCompendium.generateSpellTable();
331+
}
332+
247333
static render() {
248334
// TAGS
249335
SpellCompendium.tagButtons(SpellCompendium.TagCounts.School, SpellCompendium.UI.SchoolList);
250336
SpellCompendium.tagButtons(SpellCompendium.TagCounts.Regular, SpellCompendium.UI.TagList);
337+
SpellCompendium.tagButtons(SpellCompendium.TagCounts.Forbidden, SpellCompendium.UI.ForbiddenList);
251338

252339
// TIERS
253340
for (let i = 1; i <= 9; i++) {
254341
const tierButton = document.querySelector(`#tier${i}`);
255-
tierButton.dataset.i = i;
256-
const tier = i;
257-
tierButton.onclick = function() {
258-
const S = parseInt(tierButton.value);
259-
switch (S) {
260-
case 0:
261-
tierButton.value = S+1;
262-
SpellCompendium.tierSelection.add(tier);
263-
break;
264-
case 1:
265-
tierButton.value = 0;
266-
SpellCompendium.tierSelection.delete(tier);
267-
break;
268-
}
269-
SpellCompendium.generateSpellTable();
270-
}
342+
tierButton.dataset.tier = i;
343+
tierButton.addEventListener('click', SpellCompendium.tierButtonClickHandler);
271344
}
272345

273-
SpellCompendium.UI.RightDiv.appendChild(SpellCompendium.spellCard(SpellDatabase[0], SpellCompendium.TagDescriptions.Functional));
346+
SpellCompendium.UI.RightDiv.appendChild(SpellCompendium.spellCard(SpellDatabase[0]));
274347
SpellCompendium.generateSpellTable();
275348

276-
const downloadButton = SpellCompendium.UI.RightDiv
277-
.appendChild(document.createElement('center'))
278-
.appendChild(document.createElement('button'));
279-
downloadButton.textContent = "SAVE (.png)";
280-
downloadButton.style.textAlign = 'center';
281-
downloadButton.onclick = SpellCompendium.downloadSpell;
349+
const downloadButton = document.createElement('button');
350+
downloadButton.className = 'compendium-donwload';
351+
downloadButton.textContent = 'SAVE (.png)';
352+
downloadButton.addEventListener('click', SpellCompendium.downloadSpell);
353+
SpellCompendium.UI.RightDiv.appendChild(downloadButton);
282354
}
283355
}
284356

styles/compendium.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ table.spell {
8787
width: 600px;
8888
background-color: Ivory;
8989
}
90+
table.spelltable {
91+
border: 2px solid transparent;
92+
border-collapse: collapse;
93+
}
94+
table.spelltable td {
95+
border: 2px solid transparent;
96+
}
97+
tr.spellbrief.tag-Functional-Deprecated {
98+
font-size: 0.8em;
99+
font-style: italic;
100+
background-color: #bbbbbb44;
101+
}
102+
tr.spellbrief.spell-Forbidden {
103+
background-color: #ffaa0044;
104+
}
90105
td.spellname {
91106
font-weight: bold;
92107
text-align: center;
@@ -135,12 +150,27 @@ td {
135150
.tierselect .selector {
136151
width: 20%;
137152
}
153+
.tagselect .selector {
154+
display: block;
155+
}
156+
.tagselect .selector img {
157+
width: 14px;
158+
padding-right: 2px;
159+
}
160+
.tagselect .selector div {
161+
display: inline;
162+
}
138163
.selector[value="1"] {
139164
background-color: Cyan;
140165
}
141166
.selector[value="2"] {
142167
background-color: Red;
143168
}
169+
button.compendium-donwload {
170+
display: block;
171+
margin: 0.5em auto;
172+
padding: 0.2em 1em;
173+
}
144174

145175
#spell_creation {
146176
text-align: center;

0 commit comments

Comments
 (0)