Welcome to the second week of A Sheet Author's Journey! Last week we sketched out a rough idea of what our sheet was going to look like and assembled our tools. Today, we're going to actually start making the sheet. We're going to start our coding with the top two rows of that sketch, although we're going to hold off on the image section because we want to make sure we're going to have room for it. The code from today's post can be found in folder 2 First Code of the Tutorial Sheet . Series Posts The Beginning Do the Pug Repeating Sections and sheetworkers Style and Layout Finding our Flair! Roll on! Organizing our code Where do we start though? Well, first we need to define what the various components of our sheet are going to be. Last week we sketched out a prototype layout for the PC sheet, but we'll need an NPC sheet as well so that GM's can take advantage of the sheet as well. In addition, we'll need a settings page where users can modify how the sheet functions. At the very least, this is going to be how the sheet is switched from PC to NPC mode. Let's split our code up so that each section of each page is it's own file. This allows us to work with smaller blocks of code at a time, while not making our code so divided that it's difficult to navigate. As an added bonus, this gives us defined milestones so that we can get a sense of accomplishment while writing the sheet. So, Here's what our file structure is going to look like: First lines of code That seems like a lot of files, but splitting them up this way is going to save us lots of time scrolling looking for that one line of code that we need to change. Also, note that the files for each section start their names with an underscore. This tells prePros to not generate an HTML file for those files. Instead it only generates the html for system.pug which will include those files. Here's what the code for system.pug looks like: include scaffold/_kpug.pug
include mixins/_sheetmixins.pug
- let templateName = 'thj2e';
+hidden({name:'template start',value:`@{whisper}&{template:${templateName}} {{character_name=@{character_name}}} {{character_id=@{character_id}}}`})
+hidden({name:'sheet state',value:'settings'})
+hidden({name:'collapsed',value:''})
main#main
nav#main-nav.sheet-nav
each val in ['character','npc']
+action({name:`nav ${val}`,class:`sheet-nav__tab ${val}`,'data-i18n':`${val} sheet`,'data-i18n-title':`${val} sheet button title`,role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}})
+action({name:'nav settings',class:'pictos active sheet-nav__tab settings','data-i18n-title':'open the settings page',role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}})
|y
include articles/settings/_settings.pug
include articles/character/_character.pug
include articles/npc/_npc.pug
include rolltemplates/_thj2etemplate.pug
+kscript
//- All additional javascript files should start here A fully commented version can be found on the github repository, but lets take a look at what's going on in this file. It sure doesn't look like the code for an entire character sheet after all. include scaffold/_kpug.pug
include mixins/_sheetmixins.pug The first line here simply installs the K-scaffold so that we can use its library of PUG mixins and functions and connect our PUG and Javascript code. The second line includes a file that I've set up to hold the system specific mixins we will almost certainly be writing as we go along. Speaking of mixins, we use some in the next couple lines: +hidden({name:'template start',value:`@{whisper}&{template:${templateName}} {{character_name=@{character_name}}} {{character_id=@{character_id}}}`})
+hidden({name:'sheet state',value:'settings'})
+hidden({name:'collapsed',value:''}) Here, we're defining three hidden inputs that will be used by various pieces of the sheet. The first line just gives us an attribute we can call to include the standard roll template fields so that we don't have to type those in constantly. The other two attributes will be used by our Javascript powered navigation system that we will eventually write. Then we come to the container for our actual sheet: main#main
nav#main-nav.sheet-nav
each val in ['character','npc']
+action({name:`nav ${val}`,class:`sheet-nav__tab ${val}`,'data-i18n':`${val} sheet`,'data-i18n-title':`${val} sheet button title`,role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}})
+action({name:'nav settings',class:'pictos active sheet-nav__tab settings','data-i18n-title':'open the settings page',role:'heading','aria-level':5,trigger:{listenerFunc:'navigateSheet'}})
|y We're putting this in a main element so that our HTML will be semantic. While writing semantic HTML is not essential, it will make understanding your code easier and will help make your sheet more accessible to users that rely on screen readers. Also in this section, we define our navigation bar, which will have a button to access the character sheet, the settings sheet, and the NPC sheet. We can add additional buttons to this set as needed. Note the trigger object at the end of each of the action button declarations. This will be an object format that we'll use frequently throughout the sheet as it is how the K-scaffold writes our Javascript listeners for us. These trigger objects are defining a custom function to respond to these buttons being clicked. And finally, we've got references to each of our separate pages: include articles/settings/_settings.pug
include articles/character/_character.pug
include articles/npc/_npc.pug These are including the code for each of our pages so that the html that is generated will include all of this code. Each page is going to be an article which will include the code for each section: article#character.character
include sections/_header.pug
include sections/_attributes.pug
include sections/_defenses.pug
include sections/_weapons.pug
include sections/_armor.pug
include sections/_lineage.pug
include sections/_archetype.pug
include sections/_equipment.pug
include sections/_spells.pug Creating our first section That's pretty simple! So, let's jump into what one of these sections looks like. We'll take a look _attributes.pug here, but those first three files are written and available to view in the repository. Here's what the attributes section looks like on the paper sheet: So, we've got 6 attributes that need to be tracked, and each one has a raw score and a modifier that is derived from that score. We could write out our inputs for each of these attributes by hand, but PUG allows us to do this by iteration so that all we need to write is: -
const attributes = [
'might',
'finesse',
'resolve',
'insight',
'bearing',
'weal'
];
- varObjects.attributeNames = attributes;
section#attributes.attributes.paper-background
h5(data-i18n='score').score-head
h5(data-i18n='modifier').modifier-head
each name in attributes
+roller({name,role:'heading','aria-level':4,'data-i18n':name,trigger:{listenerFunc:'initiateRoll'}})
+number({name,class:'underlined',trigger:{affects:[`${name}_mod`]}})
+number({name:`${name} mod`,readonly:'',class:'underlined',trigger:{calculation:'calcAttribute'}}) So, we've defined an array that stores the names of all the attributes. Additionally, we're storing that array in the K-scaffold provided varObjects so that it will be available in our javascript as well (once we get to writing it). Then, we iterate through that array to create our elements. This means we only have to write the elements once, and PUG will generate each of them for us. Each attribute is going to have a clickable button that will roll a basic attribute check for the character, a number input to store the raw score, and a number input to store the modifier in. Note the trigger objects for those two number inputs. We're setting our raw score input for each attribute to affect the mod for each attribute and defining a function that we'll need to write to calculate the modifier score. That's pretty much it for this section. We've also added some classes and roles to various elements that we'll hook into when we write our SCSS and our Javascript navigation functions. Is that all!? It may not seem like we've done a lot yet, but we've got pretty much all of our basic attributes for a PC done. Next week we'll look at creating repeating sections to handle all the rest and start laying the sheet out into its basic grid. Hope you all find this helpful and hit me up with questions, suggestions, or critiques in the comments. If you're enjoying this series of posts, d rop by the Kurohyou Studios Patreon ! See the previous post | Check out the Repository | See the next post