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+
117class 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 ( / F o r b i d d e n \( ( .+ ) \) / ) [ 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
0 commit comments