<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js"></script>
<script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<link rel="icon" type="image/x-icon" href="images\bg3-mage-armour-icon.avif">
<style>
.bg {
background-color: rgb(230, 230, 230);
}
/* div {
box-shadow: unset !important;
} */
option {
background-color: rgb(240, 240, 240);
}
.testBorder {
border: 2px dashed black !important;
}
.pageBorder{
border-width: 1px;
border-color: black;
border-style: dashed;
background-color: white;
}
.centered {
display:inline-block;
text-align:center;
margin: 0;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#previewHeading{
text-align: center;
border-radius: 10px;
border-width: 2px;
border-color: black;
border-style: solid;
background-color: lightgreen;
font-family:'Lucida Grande';
}
.menu{
border-radius: 15px;
border-width: 2px;
border-color: black;
border-style: solid;
background-color: rgb(188, 188, 188);
font-family:'Lucida Grande';
}
.subMenu {
border-radius: 15px;
border-width: 2px;
background-color: rgb(205, 205, 205);
font-family:'Lucida Grande';
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.shadow1{
/* box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */
box-shadow: unset !important;
}
.AS2 {
border-radius: 15px;
border-width: 2px;
background-color: rgb(225, 225, 225);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.AS1 {
border-radius: 15px;
border-width: 2px;
/* border-color: black;
border-style: solid; */
background-color: rgb(230, 230, 230);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
font-family:'Lucida Grande';
}
.pdfFormat {
/* For PDF Thing */
box-shadow: unset !important;
border-color: rgba(100,100,100,0.25);
border-width: 1px;
border-style: solid;
}
.ASbackground {
border-radius: 15px;
border-width: 2px;
/* border-color: black;
border-style: solid; */
background-color: rgb(210, 210, 210);
/* box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */
font-family:'Lucida Grande';
}
.inField{
border-radius: 5px;
border-width: 1px;
background-color: rgb(220, 220, 220);
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
<script>
function printDiv(name) {
var divContents = document.getElementById("pageArea").innerHTML;
var divContents2 = document.getElementById("pageArea2").innerHTML;
var a = window.open('', '', 'height=1000, width=1000');
a.document.write('<html>');
a.document.write('<head>');
a.document.write('<style>')
a.document.write(".pageBorder{border-width: 1px;border-color: black;border-style: dashed; background-color: white; } .centered { display:inline-block; text-align:center; margin: 0; position: relative; top: 50%; left: 50%; transform: translate(-50%, -50%); } #previewHeading{ text-align: center; border-radius: 10px; border-width: 2px; border-color: black; border-style: solid; background-color: lightgreen; font-family:'Lucida Grande'; } .menu{ border-radius: 15px; border-width: 2px; border-color: black; border-style: solid; background-color: rgb(188, 188, 188); font-family:'Lucida Grande'; } .subMenu { border-radius: 15px; border-width: 2px; background-color: rgb(205, 205, 205); box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); font-family:'Lucida Grande'; } .AS2 { border-radius: 15px; border-width: 2px; background-color: rgb(225, 225, 225); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19); font-family:'Lucida Grande'; } .AS1 { border-radius: 15px; border-width: 2px; /* border-color: black; border-style: solid; */ background-color: rgb(230, 230, 230); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19); font-family:'Lucida Grande'; } .ASbackground { border-radius: 15px; border-width: 2px; /* border-color: black; border-style: solid; */ background-color: rgb(210, 210, 210); /* box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */ font-family:'Lucida Grande'; } .inField{ border-radius: 5px; border-width: 1px; background-color: rgb(220, 220, 220); }")
a.document.write('</style>');
a.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">');
a.document.write("<title>"+name+"'s Character Sheet</title>");
a.document.write('</head>');
a.document.write('<body>');
a.document.write('<div style="height:11in;">');
a.document.write(divContents);
a.document.write('</div>');
a.document.write('<div style="height:11in;">');
a.document.write(divContents2);
a.document.write('</div>');
a.document.write('</body>');
a.document.write('</html>');
a.document.close();
a.print();
}
</script>
<title>Character Sheet Generator</title>
</head>
<body class="bg">
<div class="row m-1">
<!-- Menus -->
<div class="row col" style="position: fixed;">
<!-- Column 1 -->
<div class="ms-4 col">
<div class="mt-3 m-auto p-3 row menu">
<input class='mt-1 mb-1 inField form-control form-control-lg shadow' type='text' id='Name' placeholder='Character Name:' name='nameField'>
<!-- Ability Score Inputs -->
<div class="mt-2 p-2 row subMenu mx-auto col-4" style="text-align: center; height: fit-content;">
<div class="col">
<b><label for="str" style="width: 40px; text-align: right;">STR</label></b>
<input type="number" id="str" name="STR" min="1" max="20" class="inField" value="10">
<br>
<b><label for="dex" class="mt-2" style="width: 40px; text-align: right;">DEX</label></b>
<input type="number" id="dex" name="DEX" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="con" class="mt-2" style="width: 40px; text-align: right;">CON</label></b>
<input type="number" id="con" name="CON" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="int" class="mt-2" style="width: 40px; text-align: right;">INT</label></b>
<input type="number" id="int" name="INT" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="wis" class="mt-2" style="width: 40px; text-align: right;">WIS</label></b>
<input type="number" id="wis" name="WIS" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="cha" class="mt-2" style="width: 40px; text-align: right;">CHA</label></b>
<input type="number" id="cha" name="CHA" min="1" max="20" class="inField mt-1" value="10">
</div>
</div>
<!-- Races And Classes -->
<div class="col subMenu mt-2 ms-3 mx-auto">
<h4 class="mt-2">Race:</h4>
<select class="form-select inField raceField" id="charRace">
<option>Human</option>
<option>Elf</option>
<option>Drow</option>
<option>Tiefling</option>
<option>Githyanki</option>
<option>Dwarf</option>
<option>Half-Elf</option>
<option>Halfling</option>
<option>Gnome</option>
<option>Dragonborn</option>
<option>Half-Orc</option>
</select>
<!-- Subrace Menus -->
<h4 class="mt-2 subraceMenu" id="subraceHeader" style="background-color: rgba(0, 0, 0, 0);">Subrace:</h4>
<!-- Elf -->
<select id="ElfMenu" class="form-select raceField subraceMenu">
<option>High Elf</option>
<option>Wood Elf</option>
</select>
<!-- Half-Elf -->
<select id="Half-ElfMenu" class="form-select raceField subraceMenu">
<option>High Half-Elf</option>
<option>Wood Half-Elf</option>
<option>Drow Half-Elf</option>
</select>
<!-- Drow -->
<select id="DrowMenu" class="form-select raceField subraceMenu">
<option>Lolth-Sworn Drow</option>
<option>Seldrine Drow</option>
</select>
<!-- Tiefling -->
<select id="TieflingMenu" class="form-select raceField subraceMenu">
<option>Asmodeus Tiefling</option>
<option>Mephistophele Tiefling</option>
<option>Zariel Tiefling</option>
</select>
<!-- Dwarf -->
<select id="DwarfMenu" class="form-select raceField subraceMenu">
<option>Gold Dwarf</option>
<option>Shield Dwarf</option>
<option>Duergar</option>
</select>
<!-- Halfling -->
<select id="HalflingMenu" class="form-select raceField subraceMenu">
<option>Lightfoot Halfling</option>
<option>Strongheart Halfling</option>
</select>
<!-- Gnome -->
<select id="GnomeMenu" class="form-select raceField subraceMenu">
<option>Rock Gnome</option>
<option>Forest Gnome</option>
<option>Deep Gnome</option>
</select>
<!-- Dragonborn -->
<select id="DragonbornMenu" class="form-select raceField subraceMenu">
<option>Black</option>
<option>Blue</option>
<option>Brass</option>
<option>Bronze</option>
<option>Copper</option>
<option>Gold</option>
<option>Green</option>
<option>Red</option>
<option>Silver</option>
<option>White</option>
</select>
<h4 class="mt-2">Class:</h4>
<div id="classesMenu">
<div class="row m-1">
<select class="col form-select inField classMenu mb-2" id="classSubMenu1">
<option>Barbarian</option>
<option>Bard</option>
<option>Cleric</option>
<option>Druid</option>
<option>Fighter</option>
<option>Monk</option>
<option>Paladin</option>
<option>Ranger</option>
<option>Rogue</option>
<option>Sorcerer</option>
<option>Warlock</option>
<option>Wizard</option>
</select>
<input type="number" id="lvl1" name="lvl" min="1" max="20" class="inField col-3 mb-2 ms-1" value="1">
</div>
</div>
<div class="row">
<button class="btn btn-secondary buttonFont col m-1 ms-2 mb-2" onclick="addClass()">Add Class</button>
<button class="btn btn-secondary buttonFont col m-1 me-2 mb-2" onclick="removeClass()">Remove Class</button>
</div>
</div>
<!-- Buttons -->
<div class="subMenu mt-3">
<div class="row col mx-auto">
<input type="file" id="charUpload" name="filename" class="col form-control ms-1 me-1 mt-3 AS1" style="background-color: rgb(230, 230, 230);">
<input type="button" value="Save" onclick="saveCharacter()" id="saveBtn" class="btn btn-success shadow buttonFont ms-1 me-1 mt-3 col-3">
</div>
<hr class="ms-3 me-3">
<div class="row col">
<input type="button" value="Print" onclick="printDiv()" id="printBtn" class="btn btn-primary buttonFont ms-3 me-1 mb-3 col">
<input type="button" value="Save as PDF" onclick="CreatePDFfromHTML()" id="cmd" class="btn btn-secondary buttonFont ms-1 me-3 mb-3 col">
</div>
</div>
<!-- Load Character Menu -->
<!-- <form action="/action_page.php" class="subMenu mt-2 col"> -->
<!-- </form> -->
</div>
<!-- To Do List -->
<!-- <div data-bs-toggle="collapse" data-bs-target="#ToDoDiv" class="menu mt-4 p-3">
<h3 style="text-align: center;"><b>To Do</b></h3>
<div id="ToDoDiv" class="collapse">
<hr>
<ul>
<li>Make it work when the window is scaled down</li>
<li>Add comments to everything so I can tell what the hell is going on</li>
<li>Add "Spell Save" and "Spell Attack" sections for casters</li>
<li>Add Subclasses</li>
<li>Dark Theme?</li>
</ul>
</div>
</div> -->
<div style="background-color: rgba(0,0,100,0.25); border: 1px solid black; border-radius: 10px;" class="mt-3 p-2">
<h3 style="text-align: center;">Notes</h3>
<hr>
<ul style="font-size: x-small;">
<li>When you go to print, if the print preview looks all funny hit cancel then ctrl+p to reopen the print dialog and it should be fixed.</li>
<li>When you save a character it will automatically send a file to your downloads folder.</li>
<li>To upload a character save, click on "Choose File", select the save file, then click "Open".</li>
<li>For both the "Weapon Proficiency" and "Feature" fields require you to press the "Add" button beside them in order to update.</li>
<li>If you acidentily added something you didn't mean to or made a mistake, mouse over the item on the preview. If you see a line through it, you can click on it and it will be removed.</li>
<li>The PDF generated by clicking "Save as PDF" will be formatted slightly diferently from the preview due to rendering issues. If you prefure the preview version over the generated PDF, you can save it via the print dialogue.</li>
</ul>
</div>
</div>
<!-- Column 2 (Spacer) -->
<div class="col">
<div style="width: 8.5in; height: 3in;"></div>
</div>
<!-- Column 3 -->
<div class="col">
<div class="mt-3 m-auto p-3 row menu">
<div class="ms-1 me-1 p-2 ps-4 pe-4 subMenu">
<h5 style="text-align: center;"><b>Additional Info</b></h5>
<div class="row">
<!-- <textarea class="col form-control" rows="1" id="addWeapons" name="text" placeholder="Weapon Proficiency"></textarea> -->
<!-- <input class="form-control col" list="wpnList" placeholder="Weapon Proficiency" id="addWeapons"> -->
<select id="addWeapons" class="form-select col pe-2">
<option value="" disabled selected style="background-color: rgb(220,220,220);">Weapon Proficiency</option>
<option>Greatswords</option>
<option>Longswords</option>
<option>Shortswords</option>
<option>Rapiers</option>
<option>Scimitars</option>
<option>Sickles</option>
<option>Daggers</option>
<hr>
<option>Morningstars</option>
<option>Maces</option>
<option>Flails</option>
<option>Greatclubs</option>
<option>Clubs</option>
<option>Warhammers</option>
<option>Mauls</option>
<option>Quarterstaves</option>
<option>Light Hammers</option>
<hr>
<option>Longbows</option>
<option>Shortbows</option>
<option>Heavy Crossbows</option>
<option>Light Crossbows</option>
<option>Hand Crossbows</option>
<hr>
<option>Greataxes</option>
<option>Battleaxes</option>
<option>Halberds</option>
<option>Glaives</option>
<option>Handaxes</option>
<hr>
<option>Spears</option>
<option>Pikes</option>
<option>Javelins</option>
<option>War Picks</option>
<option>Tridents</option>
</select>
<input type="button" value="Add" onclick="addWeapon()" class="col ms-3 btn btn-secondary buttonFont">
</div>
<div class="row mt-2">
<textarea class="col form-control" rows="1" id="addFeat" name="text" placeholder="Feature"></textarea>
<input type="button" value="Add" onclick="addFeat()" class="col ms-3 btn btn-secondary buttonFont">
</div>
</div>
<div class="subMenu m-1 mt-2">
<h5 style="text-align: center;" class="mt-2"><b>Equipment Proficiencies</b></h5>
<div class="subMenu mt-2 p-2">
<h5 class="mt-2" style="text-align: center;">Armor</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideArmor">
<label class="form-check-label" for="hideArmor">Hide Armor</label>
</div>
<hr>
<div class="form-check m-2 mb-3" style="text-align: left;">
<input class="form-check-input inField checkInput armor" type="checkbox" id="LightProf" name="Light">
<label class="form-check-label" for="LightProf">Light Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="MediumProf" name="Medium">
<label class="form-check-label" for="MediumProf">Medium Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="HeavyProf" name="Heavy">
<label class="form-check-label" for="HeavyProf">Heavy Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="ShieldsProf" name="Shields">
<label class="form-check-label" for="ShieldsProf">Shields</label>
<br>
</div>
</div>
<div class="subMenu p-2 mt-2">
<h5 class="mt-2" style="text-align: center;">Weapons</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideWeapons">
<label class="form-check-label" for="hideWeapons">Hide Weapons</label>
</div>
<hr>
<div class="form-check m-2 mb-2" id='wProfs' style="text-align: left;">
<input class="form-check-input inField checkInput wpn" type="checkbox" id="Martial" name="Martial">
<label class="form-check-label" for="Martial">Martial Weapons</label>
<br>
<input class="form-check-input inField checkInput wpn" type="checkbox" id="Simple" name="Simple">
<label class="form-check-label" for="Simple">Simple Weapons</label>
<br>
</div>
</div>
<div class="subMenu p-2 mt-2 mb-2">
<h5 class="mt-2" style="text-align: center;">Tools</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideTools">
<label class="form-check-label" for="hideTools">Hide Tools</label>
</div>
<hr>
<div class="form-check m-2 mb-2" id='wProfs' style="text-align: left;">
<input class="form-check-input inField checkInput tool" type="checkbox" name="tt" id="tt">
<label class="form-check-label" for="tt">Thieve's Tools</label>
<br>
<input class="form-check-input inField checkInput tool" type="checkbox" name="tdk" id="tdk">
<label class="form-check-label" for="tdk">Trap Disarming Kit</label>
<br>
<input class="form-check-input inField checkInput tool" type="checkbox" name="mi" id="mi">
<label class="form-check-label" for="mi">Musical Instruments</label>
<br>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Column 1 (Spacer) -->
<div class="ms-5 col"></div>
<!-- Column 2 - Preview Area-->
<div class="col mx-auto">
<div class="col m-3 mb-1 mx-auto" style="width: 8.5in;">
<h1 class="note" id="previewHeading">Preview:</h1>
</div>
<div id="previews">
<div id="pageArea" class="pageBorder shadow1 m-3 mt-1 mx-auto" style="height:11in; width: 8.5in;">
<!--Paper Size-->
<div class="centered ps-3 pe-3" style="height:10.5in; width: 8in;">
<!--Work Area-->
<!-- Character Info -->
<div class="mx-auto mt-3 row">
<div class="ASbackground col-8">
<h1 class="mt-2 AS1"><b id="charName"></b></h1>
<h4 id="raceLabel"></h4>
<h4 id="classLabel"></h4>
</div>
<div class="ASbackground col ms-2">
<h3 class="mt-3"><b>Base AC</b></h3>
<h1 class="AS1"><b id="baseAC"></b></h1>
</div>
</div>
<!-- Ability Scores -->
<div class="mt-3">
<div class="row p-3 mx-auto ASbackground" style="text-align: center;">
<div class="AS2 col m-1 p-2">
<h5>Strength</h5>
<div class="AS1">
<h1 class="AS1" id="strMod"></h1>
<h6 id="strScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Dexterity</h5>
<div class="AS1">
<h1 class="AS1" id="dexMod"></h1>
<h6 id="dexScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Constitution</h5>
<div class="AS1">
<h1 class="AS1" id="conMod"></h1>
<h6 id="conScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Intelligence</h5>
<div class="AS1">
<h1 class="AS1" id="intMod"></h1>
<h6 id="intScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Wisdom</h5>
<div class="AS1">
<h1 class="AS1" id="wisMod"></h1>
<h6 id="wisScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Charisma</h5>
<div class="AS1">
<h1 class="AS1" id="chaMod"></h1>
<h6 id="chaScore"></h6>
</div>
</div>
</div>
</div>
<div class="mt-3">
<div class="row mx-auto ASbackground p-2" style="text-align: center;">
<!-- <div class="col AS2 p-1 m-2">
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Spell Attack</h4>
<h1 id="spellAttack">8</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Spell Save</h4>
<h1 id="spellSave">8</h1>
</div>
<div class="AS1 p-1 m-2">
<h5 class="mt-2">Spell Casting Modifier</h5>
<h1 id="spellMod">8</h1>
</div>
</div> -->
<div class="col AS2 p-1 m-2">
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Movement Speed</h4>
<hr class="ms-3 me-3">
<h1 id="moveSpeed">30 ft</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Jump Distance</h4>
<hr class="ms-3 me-3">
<h1 id="jumpDist">15 ft</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Carrying Capacity</h4>
<hr class="ms-3 me-3">
<h1 id="carryCap">150 lbs</h1>
</div>
</div>
<div class="col AS2 p-1 m-2">
<h4 class="mt-2">Features & Trates</h4>
<hr class="ms-3 me-3">
<div id="featsDiv" style="text-align: justify;">
<ul id="featsList">
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="pageArea2" class="pageBorder shadow1 m-3 mt-1 mx-auto" style="height:11in; width: 8.5in;">
<!--Paper Size-->
<div class="centered ps-3 pe-3" style="height:10.5in; width: 8in;">
<!--Work Area-->
<!-- Proficiencies -->
<div class="row mt-3 mx-auto">
<div class="ASbackground mx-auto pb-3 row">
<h1 class="mt-2"><b>Proficiencies</b></h1>
<div class="col m-1 AS1">
<h3 class="mt-3">Skill Proficiencies</h3>
<hr>
<div class="form-check m-2 mb-3" style="text-align: left;">
<input style="display: inline-block;" class="form-check-input skillProfCheck checkInput" type="checkbox" id="AcrobaticsRad" name="AcrobaticsRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='AcrobaticsExp' id='AcrobaticsExpId' prevVal="off">
<label class="form-check-label" for="AcrobaticsRad">Acrobatics (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="AnimalHandlingRad" name="AnimalHandlingRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='AnimalHandlingExp' id='AnimalHandlingExpId' prevVal="off">
<label class="form-check-label" for="AnimalHandlingRad">Animal Handling (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="ArcanaRad" name="ArcanaRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='ArcanaExp' id='ArcanaExpId' prevVal="off">
<label class="form-check-label" for="ArcanaRad">Arcana (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="AthleticsRad" name="AthleticsRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='AthleticsExpId' prevVal="off">
<label class="form-check-label" for="AthleticsRad">Athletics (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="DeceptionRad" name="DeceptionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='DeceptionExpId' prevVal="off">
<label class="form-check-label" for="DeceptionRad">Deception (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="HistoryRad" name="HistoyRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='HistoryExpId' prevVal="off">
<label class="form-check-label" for="HistoryRad">History (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="InsightRad" name="InsightRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='InsightExpId' prevVal="off">
<label class="form-check-label" for="InsightRad">Insight (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="IntimidationRad" name="IntimidationRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='IntimidationExpId' prevVal="off">
<label class="form-check-label" for="IntimidationRad">Intimidation (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="InvestigationRad" name="InvestigationRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='InvestigationExpId' prevVal="off">
<label class="form-check-label" for="InvestigationRad">Investigation (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="MedicineRad" name="MedicineRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='MedicineExpId' prevVal="off">
<label class="form-check-label" for="MedicineRad">Medicine (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="NatureRad" name="NatureRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='NatureExpId' prevVal="off">
<label class="form-check-label" for="NatureRad">Nature (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PerceptionRad" name="PerceptionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PerceptionExpId' prevVal="off">
<label class="form-check-label" for="PerceptionRad">Perception (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PerformanceRad" name="PerformanceRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PerformanceExpId' prevVal="off">
<label class="form-check-label" for="PerformanceRad">Performance (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PersuasionRad" name="PersuasionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PersuasionExpId' prevVal="off">
<label class="form-check-label" for="PersuasionRad">Persuasion (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="ReligionRad" name="ReligionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='ReligionExpId' prevVal="off">
<label class="form-check-label" for="ReligionRad">Religion (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="SleightOfHandRad" name="SleightOfHandRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='SleightOfHandExpId' prevVal="off">
<label class="form-check-label" for="SleightOfHandRad">Sleight of Hand (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="StealthRad" name="StealthRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='StealthExpId' prevVal="off">
<label class="form-check-label" for="StealthRad">Stealth (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="SurvivalRad" name="SurvivalRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='SurvivalExpId' prevVal="off">
<label class="form-check-label" for="SurvivalRad">Survival (WIS)</label>
</div>
</div>
<div class="col m-1 AS1">
<h3 class="mt-3">Equipment Proficiencies</h3>
<div class="AS2 mt-2 p-2" id="armorProfDiv">
<h5 class="mt-2">Armor</h5>
<hr>
<ul id="armorProf" style="text-align: justify;">
</ul>
</div>
<div class="AS2 p-2 mt-2" id="weaponProfDiv">
<h5 class="mt-2">Weapons</h5>
<hr>
<ul id="wpnProf" style="text-align: justify;">
</ul>
</div>
<div class="AS2 p-2 mt-2 mb-2" id="toolProfDiv">
<h5 class="mt-2">Tools</h5>
<hr>
<ul id="toolProf" style="text-align: justify;">
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Column 3 (Spacer)-->
<div class="col me-5"></div>
</div>
<div id="charUploadDiv"></div>
</body>
<!-- <script type="module">
// import { jsPDF } from "jspdf";
import { jsPDF } from "https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js";
</script> -->
<script>
const { jsPDF } = window.jspdf;
$(document).ready(function () {
$(".subraceMenu").hide();
var hasSubraces = ["Elf","Half-Elf","Drow","Tiefling","Dwarf","Halfling","Gnome","Dragonborn"];
var noSubraces = ["Human","Half-Orc","Githyanki"]
var profs = ['Acrobatics','AnimalHandling','Arcana','Athletics','Deception','History','Insight','Intimidation','Investigation','Medicine','Nature','Perception','Performance','Persuasion','Religion','SleightOfHand','Stealth','Survival']
var abilities = ['str','dex','con','int','wis','cha']
var showExp = false;
function char(){
this.abilityScore = {str:'', dex:"", con:"", int:"", wis:"", cha:""};
this.race = "";
this.classDescription = "";
this.FeaturesAndTrates = [];
this.armorProfs = [];
this.weaponProfs = [];
this.toolProfs = [];
this.name = "";
this.abilityProfs = [];
this.abilityExpertise = [];
this.abilityProfs1 = [];
this.abilityExpertise1 = [];
this.baseRase = '';
this.subRace = '';
this.lvl = 0;
}
const charSave = new char;
// charSave.classDescription = "";
charSave.armorProfs = [1];
charSave.weaponProfs = [1];
charSave.toolProfs = [1];
charSave.abilityExpertise = [];
charSave.abilityProfs = [];
charSave.race = $(".raceField").val();
charSave.FeaturesAndTrates = [1];
loadFileAsText = function (){
var fileToLoad = document.getElementById("charUpload").files[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent){
var textFromFileLoaded = fileLoadedEvent.target.result;
// console.log(textFromFileLoaded);
document.getElementById("charUploadDiv").value = textFromFileLoaded;
};
fileReader.readAsText(fileToLoad, "UTF-8");
}
showExpertise = function() {
for (let i = 0; i<profs.length; i++) {
$("#"+profs[i]+"ExpId").removeClass('d-none');
}
}
hideExpertise = function () {
for (let i = 0; i<profs.length; i++) {
$("#"+profs[i]+"ExpId").addClass('d-none');
}
};
var exp = [];
updateToolMenu = function(){
for (let i = 0; i<charSave.toolProfs.length-1; i++){
var target = charSave.toolProfs[i+1];
if (target == "Thieve's Tools") {
$("#tt").prop('checked', true);
} else if (target == "Trap Disarming Kits") {
$("#tdk").prop('checked', true);
} else if (target == "Musical Instruments") {
$("#mi").prop('checked', true);
}
}
$("#toolProf").empty();
for (let i = 1; i<charSave.toolProfs.length; i++) {
$("#toolProf").append("<li class='toolLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.toolProfs[i]+"</li>");
}
}
loadCharacter = function () {
loadFileAsText()
setTimeout(function(){
// console.log("Div Value: "+$("#charUploadDiv").val())
var uploadedCharJSON = $("#charUploadDiv").val()
// console.log("uploadedCharJSON: "+uploadedCharJSON)
var parsedCharJSON = JSON.parse(uploadedCharJSON);
// console.log(parsedCharJSON);
// console.log(parsedCharJSON.name)
charSave.armorProfs = parsedCharJSON.armorProfs;
charSave.weaponProfs = parsedCharJSON.weaponProfs;
charSave.toolProfs = parsedCharJSON.toolProfs;
charSave.abilityExpertise1 = parsedCharJSON.abilityExpertise;
charSave.abilityProfs1 = parsedCharJSON.abilityProfs;
charSave.abilityScore = parsedCharJSON.abilityScore;
charSave.race = parsedCharJSON.race;
charSave.FeaturesAndTrates = parsedCharJSON.FeaturesAndTrates;
charSave.classDescription = parsedCharJSON.classDescription;
charSave.name = parsedCharJSON.name;
charSave.baseRase = parsedCharJSON.baseRase;
charSave.subRace = parsedCharJSON.subRace;
// console.log(charSave.abilityProfs1);
// console.log(charSave.abilityExpertise1);
$("#charName").text(charSave.name);
$("#Name").val(charSave.name);
$("#charRace").val(parsedCharJSON.baseRase);
if (hasSubraces.includes(charSave.baseRase)){
$("#subraceHeader").show();
}
$("#"+parsedCharJSON.baseRase+"Menu").show();
$("#"+parsedCharJSON.baseRase+"Menu").val(charSave.subRace);
$("#str").val(charSave.abilityScore['str']);
$("#dex").val(charSave.abilityScore['dex']);
$("#con").val(charSave.abilityScore['con']);
$("#int").val(charSave.abilityScore['int']);
$("#wis").val(charSave.abilityScore['wis']);
$("#cha").val(charSave.abilityScore['cha']);
if (parsedCharJSON.classDescription.includes("Bard") || charSave.classDescription.includes("Rogue")) {
showExpertise();
} else {
hideExpertise();
}
if (parsedCharJSON.classDescription.includes("-")){
// console.log(cMenus);
let text = parsedCharJSON.classDescription;
let arr = text.split(' ')
let countDashes = text.split("-").length-1;
for (let i = 0; i<countDashes; i++) {
addClass()
}
for (let i = 0; i<cMenus; i++) {
if (i == 0){
// console.log(arr);
$("#classSubMenu"+(i+1)).val(arr[0])
$("#lvl"+(i+1)).val(arr[1][1]);
// console.log("lvl: "+arr[(i*4)+1][1])
charSave.lvl = charSave.lvl+parseInt(arr[(i*4)+1][1]);
} else {
// console.log(arr[i*4]);
$("#classSubMenu"+(i+1)).val(arr[i*4])
$("#lvl"+(i+1)).val(arr[(i*4)+1][1]);
// console.log("lvl: "+arr[(i*4)+1][1])
charSave.lvl = charSave.lvl+parseInt(arr[(i*4)+1][1]);
}
}
}
for (let i = 0; i<charSave.abilityProfs1.length; i++){
$("#"+charSave.abilityProfs1[i]+"Rad").attr('checked', true);
}
for (let i = 0; i<charSave.abilityExpertise1.length; i++){
$("#"+charSave.abilityExpertise1[i]+"ExpId").attr('checked', true);
}
for (let i = 0; i<charSave.armorProfs.length-1; i++){
// console.log(charSave.armorProfs[i+1]);
if (charSave.armorProfs[i+1] != "Shields"){
let target = charSave.armorProfs[i+1].replace(" Armor", "");
$("#"+target+"Prof").attr('checked', true);
} else {
let target = charSave.armorProfs[i+1];
$("#"+target+"Prof").attr('checked', true);
}
}
for (let i = 0; i<charSave.weaponProfs.length-1; i++){
// console.log(charSave.weaponProfs[i+1]);
let target = charSave.weaponProfs[i+1].replace(" Weapons", "")
$("#"+target).attr('checked', true);
}
updateToolMenu();
updatePreview();
},50)
// charSave.abilityExpertise = exp;
}
var cMenus = 1;
addClass = function() {
cMenus++
// console.log("Class Menu Count: "+cMenus);
$("#classesMenu").append('<div class="row m-1" id="cMen'+cMenus+'"><select onchange="updatePreview()" class="col form-select inField classMenu mb-2" id="classSubMenu'+cMenus+'"><option>Barbarian</option><option>Bard</option><option>Cleric</option><option>Druid</option><option>Fighter</option><option>Monk</option><option>Paladin</option><option>Ranger</option><option>Rogue</option><option>Sorcerer</option><option>Warlock</option><option>Wizard</option></select><input type="number" id="lvl'+cMenus+'" name="lvl" min="1" max="20" class="inField col-3 mb-2 ms-1" onclick="updatePreview()" value="1"></div>')
updateClassDescription();
updatePreview();
}
updateClassDescription = function(){
var menus = $(".classMenu");
charSave.classDescription = '';
// console.log(menus.length);
for (let i = 0; i<menus.length; i++) {
if (i >= 1) {
charSave.classDescription = charSave.classDescription + " - " + $("#classSubMenu"+(i+1)).val() + " (" + $("#lvl"+(i+1)).val() + ") ";
} else {
charSave.classDescription = charSave.classDescription+ $("#classSubMenu"+(i+1)).val() + " (" + $("#lvl"+(i+1)).val() + ") ";
}
}
if (charSave.classDescription.includes("Bard") || charSave.classDescription.includes("Rogue")) {
showExpertise();
} else {
hideExpertise();
}
}
removeClass = function() {
$("#cMen" + cMenus).remove();
cMenus--
if (cMenus < 1) {
cMenus = 1;
}
updateClassDescription();
updatePreview();
}
$(".classMenu").change( function () {
updateClassDescription();
})
mouseOverLi = function(itm) {
$(itm).css("text-decoration","line-through");
$(itm).append(" ⦻");
}
mouseLeaveLi = function(itm) {
$(itm).css("text-decoration","none");
var txt = $(itm).text();
$(itm).text(txt.split(" ⦻")[0]);
}
clickLi = function(itm) {
if ($(itm).hasClass("wpnLabel")) {
var foritm = $(itm).attr("for");
console.log(foritm);
$("#" + foritm).remove()
$("." + foritm).remove()
}
if ($(itm).hasClass("armorLi")) {
console.log("Raw Text: "+$(itm).text());
// console.log("Altered Text: "+idStr);
if ($(itm).text() != "Shields ⦻") {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
var idStr = target.replace(" Armor", "");
$("#"+(idStr)+"Prof").prop('checked', false);
let x = charSave.armorProfs.splice(i,1);
}
}
} else {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
$("#"+(target)+"Prof").prop('checked', false);
}
}
}
} else if ($(itm).hasClass("wpnLi")) {
target = ($(itm).text().replace(" ⦻", ""));
console.log("target = " + target);
for (let i = 1; i<charSave.weaponProfs.length; i++) {
if (charSave.weaponProfs[i] == target) {
var idStr = target.replace(" Weapons", "");
$("#"+(idStr)).prop('checked', false);
let x = charSave.weaponProfs.splice(i,1);
// console.log("i = "+ i + " list = "+weapon);
}
}
} else if ($(itm).hasClass("toolLi")) {
target = $(itm).text().replace(" ⦻","")
console.log("Target: ",target);
if (target == "Thieve's Tools") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#tt").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
} else if (target == "Trap Disarming Kits") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#tdk").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
} else if (target == "Musical Instruments") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#mi").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
}
} else if ($(itm).hasClass("featItm")) {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.FeaturesAndTrates.length; i++) {
if (charSave.FeaturesAndTrates[i] == target) {
let x = charSave.FeaturesAndTrates.splice(charSave.FeaturesAndTrates.indexOf(target),1);
}
}
}
$(itm).remove();
updatePreview();
}
addWeapon = function() {
charSave.weaponProfs.push($("#addWeapons").val());
updatePreview();
}
addFeat = function() {
$("#featsList").append("<li class='listItem featItm' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>" + $("#addFeat").val() + "</li>");
// $("#featsDiv").append("<br>");
charSave.FeaturesAndTrates.push($("#addFeat").val());
}
updateFeats = function () {
$("#featsList").empty();
for (let i = 1; i<charSave.FeaturesAndTrates.length; i++){
$("#featsList").append("<li class='listItem featItm' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>" + charSave.FeaturesAndTrates[i] + "</li>");
// $("#featsDiv").append("<br>");
}
}
$(".raceField").change(function() {
// $(".subraceMenu").hide();
if(hasSubraces.includes($(this).val())) {
$(".subraceMenu").hide();
$("#subraceHeader").show();
$("#"+$(this).val()+"Menu").show();
console.log("Has Subrace")
charSave.race = $("#"+$(this).val()+"Menu").val();
$("#raceLabel").text(charSave.race);
} else if(noSubraces.includes($(this).val())) {
$(".subraceMenu").hide();
charSave.race = $(this).val();
$("#raceLabel").text(charSave.race);
} else {
charSave.race = $(this).val();
$("#raceLabel").text(charSave.race);
};
console.log("Race Changed to "+charSave.race);
if($(this).val() == 'Dwarf' || $(this).val() == 'Gnome' || $(this).val() == 'Halfling') {
$("#moveSpeed").text("25 ft");
} else if(charSave.race == "Wood Half-Elf" || charSave.race == "Wood Elf"){
$("#moveSpeed").text("35 ft");
} else {
$("#moveSpeed").text("30 ft");
};
});
updateCharacter = function() {
charSave.name = $("#charName").text();
for (let i=0; i<abilities.length; i++){
// console.log(abilities[i])
charSave.abilityScore[abilities[i]] = $("#"+abilities[i]).val();
}
// console.log(charSave.abilityScore);
}
updatePreview = function() {
charSave.baseRase = $("#charRace").val();
charSave.subRace = charSave.race;
// console.log("Div Value: "+$("#charUploadDiv").val())
var jumpDistance;
var carryCap;
updateClassDescription();
updateFeats();
if($('#charRace').val() == 'Dwarf' || $('#charRace').val() == 'Gnome' || $('#charRace').val() == 'Halfling') {
$("#moveSpeed").text("25 ft");
} else if(charSave.race == "Wood Half-Elf" || charSave.race == "Wood Elf"){
$("#moveSpeed").text("35 ft");
} else {
$("#moveSpeed").text("30 ft");
};
$("#raceLabel").text(charSave.race);
$("#classLabel").text(charSave.classDescription);
for (let i = 0; i<abilities.length; i++) {
var id = abilities[i];
var score = $("#"+abilities[i]).val();
$("#"+id.toString()+"Score").text(score);
var mod = (score-10)/2;
var mod = Math.floor(mod);
if (mod < 0) {
$("#"+id.toString()+"Mod").text(mod.toString());
} else {
$("#"+id.toString()+"Mod").text("+"+mod.toString());
}
}
if ($("#Name").val() == "") {
$("#charName").text("Tav");
$("#printBtn").attr('onclick', 'printDiv("Tav")')
charSave.name = "Tav";
} else {
$("#charName").text($("#Name").val());
$("#printBtn").attr('onclick', 'printDiv("'+$("#Name").val()+'")')
charSave.name = $("#Name").val();
}
jumpDistance = 15 + (3*$("#strMod").text())
if (jumpDistance < 15) {
jumpDistance = 15;
}
$("#jumpDist").text(jumpDistance + " ft");
carryCap = 80+(20*$("#str").val());
$("#carryCap").text(carryCap + " lbs");
var dexMod = $("#dex").val()
dexMod = (dexMod-10)/2;
var baseAC = 10+Math.floor(dexMod);
$("#baseAC").text(baseAC.toString());
// console.log("--- Preview Updated ---")
charSave.abilityProfs = [];
charSave.abilityExpertise = [];
for (let i = 0; i<profs.length; i++) {
var skill = profs[i];
if ($("#"+skill+"Rad").is(':checked')) {
// console.log(skill+" is checked")
$("#"+skill+"Rad").attr("checked", true);
charSave.abilityProfs.push(skill);
} else {
// console.log(skill+" is unchecked")
$("#"+skill+"Rad").attr("checked", false);
// charSave.abilityProfs.splice(charSave.abilityProfs.indexOf(skill),i)
}
if ($("#"+skill+"ExpId").is(':checked')) {
// console.log(skill+" is checked")
$("#"+skill+"EspId").attr("checked", true);
charSave.abilityExpertise.push(skill);
} else {
// console.log(skill+" is unchecked")
$("#"+skill+"ExpId").attr("checked", false);
// charSave.abilityProfs.splice(charSave.abilityProfs.indexOf(skill),i)
}
}
$("#armorProf").empty();
for (let i = 1; i<charSave.armorProfs.length; i++) {
$("#armorProf").append("<li class='armorLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.armorProfs[i]+"</li>");
}
$("#wpnProf").empty();
for (let i = 1; i<charSave.weaponProfs.length; i++) {
$("#wpnProf").append("<li class='wpnLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.weaponProfs[i]+"</li>");
}
$("#toolProf").empty();
for (let i = 1; i<charSave.toolProfs.length; i++) {
$("#toolProf").append("<li class='toolLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.toolProfs[i]+"</li>");
}
updateToolMenu();
updateCharacter();
// console.log(charSave);
}
$(".inField").change(function() {
var target = '';
if ($(this).attr('id') == 'hideArmor'){
if ($(this).prop('checked') == true) {
$("#armorProfDiv").hide();
} else {
$("#armorProfDiv").show();
}
} else if ($(this).attr('id') == 'hideWeapons'){
if ($(this).prop('checked') == true) {
$("#weaponProfDiv").hide();
} else {
$("#weaponProfDiv").show();
}
} else if ($(this).attr('id') == 'hideTools'){
if ($(this).prop('checked') == true) {
$("#toolProfDiv").hide();
} else {
$("#toolProfDiv").show();
}
};
if ($(this).hasClass("checkInput") && $(this).prop('checked') == true) {
if ($(this).hasClass("armor")) {
// console.log("Is Armor")
if ($(this).attr('name') != "Shields") {
charSave.armorProfs.push($(this).attr('name')+" Armor");
} else {
charSave.armorProfs.push($(this).attr('name'));
}
}
if ($(this).hasClass("wpn")) {
charSave.weaponProfs.push($(this).attr('name')+" Weapons");
}
if ($(this).hasClass("tool")) {
if ($(this).attr('name') == "tt") {
charSave.toolProfs.push("Thieve's Tools");
} else if ($(this).attr('name') == "tdk") {
charSave.toolProfs.push("Trap Disarming Kits");
} else if ($(this).attr('name') == "mi") {
charSave.toolProfs.push("Musical Instruments");
}
}
} else {
if ($(this).hasClass("armor")) {
// console.log("Is Armor")
if ($(this).attr('name') != "Shields") {
target = ($(this).attr('name')+" Armor");
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
}
}
} else {
target = ($(this).attr('name'));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
}
}
}
}
if ($(this).hasClass("wpn")) {
target = ($(this).attr('name')+" Weapons");
// console.log("target = " + target);
for (let i = 1; i<charSave.weaponProfs.length; i++) {
if (charSave.weaponProfs[i] == target) {
let x = charSave.weaponProfs.splice(i,1);
}
}
}
if ($(this).hasClass("tool")) {
if ($(this).attr('name') == "tt") {
target = "Thieve's Tools";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
} else if ($(this).attr('name') == "tdk") {
target = "Trap Disarming Kits";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
} else if ($(this).attr('name') == "mi") {
target = "Musical Instruments";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
}
}
}
// console.log("inField Updated");
updatePreview()
})
$(".checkInput").change(function() {
// console.log($(this).attr('id'))
$(this).attr("checked", true);
updatePreview();
});
$("#charUpload").change(function(){
loadCharacter();
});
$("[type='radio']").on('click', function () {
if ($(this).attr('prevVal') == 'on') {
$(this).attr('prevVal','off')
$(this).prop('checked', false);
$(this).attr('checked', false);
} else {
$(this).attr('prevVal','on')
$(this).prop('checked', true);
$(this).attr('checked', true);
}
});
updatePreview()
saveCharacter = function() {
const charSaveJSON = JSON.stringify(charSave);
// console.log("JSON-ified charSave: "+ charSaveJSON);
function downloadString(text, fileType, fileName) {
var blob = new Blob([text], { type: fileType });
var a = document.createElement('a');
a.download = fileName;
a.href = URL.createObjectURL(blob);
a.dataset.downloadurl = [fileType, a.download, a.href].join(':');
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function() { URL.revokeObjectURL(a.href); }, 1500);
}
// downloadString("a,b,c\n1,2,3", "text/csv", "myCSV.csv")
downloadString(charSaveJSON, "text/plain", charSave.name+" - lvl("+charSave.lvl+").txt")
}
var doc = new jsPDF();
var specialElementHandlers = {
'#editor': function (element, renderer) {
return true;
}
};
//Create PDf from HTML...
CreatePDFfromHTML = function () {
$(".pageBorder").css("border-color", "white");
$(".AS1").addClass("pdfFormat");
$(".AS2").addClass("pdfFormat");
$(".ASBackground").addClass("pdfFormat");
var HTML_Width = $("#pageArea").width();
var HTML_Height = $("#pageArea").height();
var canvas_image_width = HTML_Width;
var canvas_image_height = HTML_Height;
var top_left_margin = 0;
asRatio = 11/8.5;
var PDF_Width = HTML_Width + (top_left_margin * 2);
var PDF_Height = HTML_Height + (top_left_margin * 2);
var totalPDFPages = 1;
console.log("HTML Width: "+HTML_Width+" HTML Height: "+HTML_Height);
console.log("PDF Width: "+PDF_Width+" PDF Height: "+PDF_Height);
var len = 2; //$x(".//body/div/div").length
var divIds = ["#pageArea","#pageArea2"]
var pdf = new jsPDF('p', 'pt',[PDF_Width, PDF_Height]);
var position = 0;
// Hide
for (let i = 1;i <= len; i++){
html2canvas(document.querySelector(divIds[i-1]),
{dpi: 600, // Set to 300 DPI
scale: 5, // Adjusts your resolution
height: PDF_Height,
width: PDF_Width
}).then(canvas => {
// pdf.addImage(canvas.toDataURL("images/png", 1), 'PNG', 0,position, 210, 295);
var imgData = canvas.toDataURL("image/jpeg", 1.0);
pdf.addImage(imgData, 'PNG', top_left_margin, top_left_margin, canvas_image_width, canvas_image_height);
if (i == len){
// pdf.save('sample-file.pdf');
window.open(pdf.output('bloburl'));
}else{
pdf.addPage();
}
});
}
$(".pageBorder").css("border-color", "black");
$(".AS1").removeClass("pdfFormat");
$(".AS2").removeClass("pdfFormat");
$(".ASBackground").removeClass("pdfFormat");
}
});
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js"></script>
<script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,50..900;1,50..900&display=swap" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="images\bg3-enlarge-reduce-icon.avif">
<style>
.bg {
background-color: rgb(230, 230, 230);
font-family: 'Noto Serif' !important;
}
/* div {
box-shadow: unset !important;
} */
option {
background-color: rgb(240, 240, 240);
}
.testBorder {
border: 2px dashed black !important;
}
.pageBorder{
border-width: 1px;
border-color: black;
border-style: dashed;
background-color: white;
}
.centered {
display:inline-block;
text-align:center;
margin: 0;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#previewHeading{
text-align: center;
border-radius: 10px;
border-width: 2px;
border-color: black;
border-style: solid;
background-color: lightgreen;
/* font-family:'Lucida Grande'; */
}
.menu{
border-radius: 15px;
border-width: 2px;
border-color: black;
border-style: solid;
background-color: rgb(188, 188, 188);
/* font-family:'Lucida Grande'; */
}
.subMenu {
border-radius: 15px;
border-width: 2px;
background-color: rgb(205, 205, 205);
/* font-family:'Lucida Grande'; */
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.shadow1{
/* box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */
box-shadow: unset !important;
}
.AS2 {
border-radius: 15px;
border-width: 2px;
background-color: rgb(225, 225, 225);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.AS1 {
border-radius: 15px;
border-width: 2px;
/* border-color: black;
border-style: solid; */
background-color: rgb(230, 230, 230);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
/* font-family:'Lucida Grande'; */
}
.pdfFormat {
/* For PDF Thing */
box-shadow: unset !important;
border-color: rgba(100,100,100,0.25);
border-width: 1px;
border-style: solid;
}
.ASbackground {
border-radius: 15px;
border-width: 2px;
/* border-color: black;
border-style: solid; */
background-color: rgb(210, 210, 210);
/* box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */
/* font-family:'Lucida Grande'; */
}
.inField{
border-radius: 5px;
border-width: 1px;
background-color: rgb(220, 220, 220);
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"></script>
<script>
function printDiv(name) {
var divContents = document.getElementById("pageArea").innerHTML;
var divContents2 = document.getElementById("pageArea2").innerHTML;
var a = window.open('', '', 'height=1000, width=1000');
a.document.write('<html>');
a.document.write('<head><link href="https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,50..900;1,50..900&display=swap" rel="stylesheet">');
a.document.write('<style>')
a.document.write("body {font-family: 'Noto Serif' !important;}.pageBorder{border-width: 1px;border-color: black;border-style: dashed; background-color: white; } .centered { display:inline-block; text-align:center; margin: 0; position: relative; top: 50%; left: 50%; transform: translate(-50%, -50%); } #previewHeading{ text-align: center; border-radius: 10px; border-width: 2px; border-color: black; border-style: solid; background-color: lightgreen; font-family:'Lucida Grande'; } .menu{ border-radius: 15px; border-width: 2px; border-color: black; border-style: solid; background-color: rgb(188, 188, 188); } .subMenu { border-radius: 15px; border-width: 2px; background-color: rgb(205, 205, 205); box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .AS2 { border-radius: 15px; border-width: 2px; background-color: rgb(225, 225, 225); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .AS1 { border-radius: 15px; border-width: 2px; /* border-color: black; border-style: solid; */ background-color: rgb(230, 230, 230); box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .ASbackground { border-radius: 15px; border-width: 2px; /* border-color: black; border-style: solid; */ background-color: rgb(210, 210, 210); /* box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); */ } .inField{ border-radius: 5px; border-width: 1px; background-color: rgb(220, 220, 220); }")
a.document.write('</style>');
a.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">');
a.document.write("<title>"+name+"'s Character Sheet</title>");
a.document.write('</head>');
a.document.write('<body>');
a.document.write('<div style="height:11in;">');
a.document.write(divContents);
a.document.write('</div>');
a.document.write('<div style="height:11in;">');
a.document.write(divContents2);
a.document.write('</div>');
a.document.write('</body>');
a.document.write('</html>');
a.document.close();
a.print();
}
</script>
<title>Character Sheet Generator - Mobile</title>
</head>
<body class="bg">
<div class="m-1">
<!-- Menus -->
<div class="col">
<div class="col">
<div class="mt-3 m-auto p-3 row menu">
<input class='mt-1 mb-1 inField form-control form-control-lg shadow' type='text' id='Name' placeholder='Character Name:' name='nameField'>
<!-- Ability Score Inputs -->
<div class="mt-2 p-2 row subMenu mx-auto col-4" style="text-align: center; height: fit-content;">
<div class="col">
<b><label for="str" style="width: 40px; text-align: right;">STR</label></b>
<input type="number" id="str" name="STR" min="1" max="20" class="inField" value="10">
<br>
<b><label for="dex" class="mt-2" style="width: 40px; text-align: right;">DEX</label></b>
<input type="number" id="dex" name="DEX" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="con" class="mt-2" style="width: 40px; text-align: right;">CON</label></b>
<input type="number" id="con" name="CON" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="int" class="mt-2" style="width: 40px; text-align: right;">INT</label></b>
<input type="number" id="int" name="INT" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="wis" class="mt-2" style="width: 40px; text-align: right;">WIS</label></b>
<input type="number" id="wis" name="WIS" min="1" max="20" class="inField mt-1" value="10">
<br>
<b><label for="cha" class="mt-2" style="width: 40px; text-align: right;">CHA</label></b>
<input type="number" id="cha" name="CHA" min="1" max="20" class="inField mt-1" value="10">
</div>
</div>
<!-- Races And Classes -->
<div class="col subMenu mt-2 ms-3 mx-auto">
<h4 class="mt-2">Race:</h4>
<select class="form-select inField raceField" id="charRace">
<option>Human</option>
<option>Elf</option>
<option>Drow</option>
<option>Tiefling</option>
<option>Githyanki</option>
<option>Dwarf</option>
<option>Half-Elf</option>
<option>Halfling</option>
<option>Gnome</option>
<option>Dragonborn</option>
<option>Half-Orc</option>
</select>
<!-- Subrace Menus -->
<h4 class="mt-2 subraceMenu" id="subraceHeader" style="background-color: rgba(0, 0, 0, 0);">Subrace:</h4>
<!-- Elf -->
<select id="ElfMenu" class="form-select raceField subraceMenu">
<option>High Elf</option>
<option>Wood Elf</option>
</select>
<!-- Half-Elf -->
<select id="Half-ElfMenu" class="form-select raceField subraceMenu">
<option>High Half-Elf</option>
<option>Wood Half-Elf</option>
<option>Drow Half-Elf</option>
</select>
<!-- Drow -->
<select id="DrowMenu" class="form-select raceField subraceMenu">
<option>Lolth-Sworn Drow</option>
<option>Seldrine Drow</option>
</select>
<!-- Tiefling -->
<select id="TieflingMenu" class="form-select raceField subraceMenu">
<option>Asmodeus Tiefling</option>
<option>Mephistophele Tiefling</option>
<option>Zariel Tiefling</option>
</select>
<!-- Dwarf -->
<select id="DwarfMenu" class="form-select raceField subraceMenu">
<option>Gold Dwarf</option>
<option>Shield Dwarf</option>
<option>Duergar</option>
</select>
<!-- Halfling -->
<select id="HalflingMenu" class="form-select raceField subraceMenu">
<option>Lightfoot Halfling</option>
<option>Strongheart Halfling</option>
</select>
<!-- Gnome -->
<select id="GnomeMenu" class="form-select raceField subraceMenu">
<option>Rock Gnome</option>
<option>Forest Gnome</option>
<option>Deep Gnome</option>
</select>
<!-- Dragonborn -->
<select id="DragonbornMenu" class="form-select raceField subraceMenu">
<option>Black</option>
<option>Blue</option>
<option>Brass</option>
<option>Bronze</option>
<option>Copper</option>
<option>Gold</option>
<option>Green</option>
<option>Red</option>
<option>Silver</option>
<option>White</option>
</select>
<h4 class="mt-2">Class:</h4>
<div id="classesMenu">
<div class="row m-1">
<select class="col form-select inField classMenu mb-2" id="classSubMenu1">
<option>Barbarian</option>
<option>Bard</option>
<option>Cleric</option>
<option>Druid</option>
<option>Fighter</option>
<option>Monk</option>
<option>Paladin</option>
<option>Ranger</option>
<option>Rogue</option>
<option>Sorcerer</option>
<option>Warlock</option>
<option>Wizard</option>
</select>
<input type="number" id="lvl1" name="lvl" min="1" max="20" class="inField col-3 mb-2 ms-1" value="1">
</div>
</div>
<div class="row">
<button class="btn btn-secondary buttonFont col m-1 ms-2 mb-2" onclick="addClass()">Add Class</button>
<button class="btn btn-secondary buttonFont col m-1 me-2 mb-2" onclick="removeClass()">Remove Class</button>
</div>
</div>
<!-- Buttons -->
<div class="subMenu mt-3">
<div class="row col mx-auto">
<input type="file" id="charUpload" name="filename" class="col form-control ms-1 me-1 mt-3 AS1" style="background-color: rgb(230, 230, 230);">
<input type="button" value="Save" onclick="saveCharacter()" id="saveBtn" class="btn btn-success shadow buttonFont ms-1 me-1 mt-3 col-3">
</div>
<hr class="ms-3 me-3">
<div class="row col">
<input type="button" value="Print" onclick="printDiv()" id="printBtn" class="btn btn-primary buttonFont ms-3 me-1 mb-3 col">
<input type="button" value="Save as PDF" onclick="CreatePDFfromHTML()" id="cmd" class="btn btn-secondary buttonFont ms-1 me-3 mb-3 col">
</div>
</div>
<!-- Load Character Menu -->
<!-- <form action="/action_page.php" class="subMenu mt-2 col"> -->
<!-- </form> -->
</div>
<!-- To Do List -->
<!-- <div data-bs-toggle="collapse" data-bs-target="#ToDoDiv" class="menu mt-4 p-3">
<h3 style="text-align: center;"><b>To Do</b></h3>
<div id="ToDoDiv" class="collapse">
<hr>
<ul>
<li>Make it work when the window is scaled down</li>
<li>Add comments to everything so I can tell what the hell is going on</li>
<li>Add "Spell Save" and "Spell Attack" sections for casters</li>
<li>Add Subclasses</li>
<li>Dark Theme?</li>
</ul>
</div>
</div> -->
</div>
<div class="col">
<div class="mt-3 m-auto p-3 row menu">
<div class="ms-1 me-1 p-2 ps-4 pe-4 subMenu">
<h5 style="text-align: center;"><b>Additional Info</b></h5>
<div class="row">
<!-- <textarea class="col form-control" rows="1" id="addWeapons" name="text" placeholder="Weapon Proficiency"></textarea> -->
<!-- <input class="form-control col" list="wpnList" placeholder="Weapon Proficiency" id="addWeapons"> -->
<select id="addWeapons" class="form-select col pe-2">
<option value="" disabled selected style="background-color: rgb(220,220,220);">Weapon Proficiency</option>
<option>Greatswords</option>
<option>Longswords</option>
<option>Shortswords</option>
<option>Rapiers</option>
<option>Scimitars</option>
<option>Sickles</option>
<option>Daggers</option>
<hr>
<option>Morningstars</option>
<option>Maces</option>
<option>Flails</option>
<option>Greatclubs</option>
<option>Clubs</option>
<option>Warhammers</option>
<option>Mauls</option>
<option>Quarterstaves</option>
<option>Light Hammers</option>
<hr>
<option>Longbows</option>
<option>Shortbows</option>
<option>Heavy Crossbows</option>
<option>Light Crossbows</option>
<option>Hand Crossbows</option>
<hr>
<option>Greataxes</option>
<option>Battleaxes</option>
<option>Halberds</option>
<option>Glaives</option>
<option>Handaxes</option>
<hr>
<option>Spears</option>
<option>Pikes</option>
<option>Javelins</option>
<option>War Picks</option>
<option>Tridents</option>
</select>
<input type="button" value="Add" onclick="addWeapon()" class="col ms-3 btn btn-secondary buttonFont">
</div>
<div class="row mt-2">
<textarea class="col form-control" rows="1" id="addFeat" name="text" placeholder="Feature"></textarea>
<input type="button" value="Add" onclick="addFeat()" class="col ms-3 btn btn-secondary buttonFont">
</div>
</div>
<div class="subMenu m-1 mt-2">
<h5 style="text-align: center;" class="mt-2"><b>Equipment Proficiencies</b></h5>
<div class="subMenu mt-2 p-2">
<h5 class="mt-2" style="text-align: center;">Armor</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideArmor">
<label class="form-check-label" for="hideArmor">Hide Armor</label>
</div>
<hr>
<div class="form-check m-2 mb-3" style="text-align: left;">
<input class="form-check-input inField checkInput armor" type="checkbox" id="LightProf" name="Light">
<label class="form-check-label" for="LightProf">Light Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="MediumProf" name="Medium">
<label class="form-check-label" for="MediumProf">Medium Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="HeavyProf" name="Heavy">
<label class="form-check-label" for="HeavyProf">Heavy Armor</label>
<br>
<input class="form-check-input inField checkInput armor" type="checkbox" id="ShieldsProf" name="Shields">
<label class="form-check-label" for="ShieldsProf">Shields</label>
<br>
</div>
</div>
<div class="subMenu p-2 mt-2">
<h5 class="mt-2" style="text-align: center;">Weapons</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideWeapons">
<label class="form-check-label" for="hideWeapons">Hide Weapons</label>
</div>
<hr>
<div class="form-check m-2 mb-2" id='wProfs' style="text-align: left;">
<input class="form-check-input inField checkInput wpn" type="checkbox" id="Martial" name="Martial">
<label class="form-check-label" for="Martial">Martial Weapons</label>
<br>
<input class="form-check-input inField checkInput wpn" type="checkbox" id="Simple" name="Simple">
<label class="form-check-label" for="Simple">Simple Weapons</label>
<br>
</div>
</div>
<div class="subMenu p-2 mt-2 mb-2">
<h5 class="mt-2" style="text-align: center;">Tools</h5>
<div class="form-check form-switch ms-2">
<input class="form-check-input inField" type="checkbox" id="hideTools">
<label class="form-check-label" for="hideTools">Hide Tools</label>
</div>
<hr>
<div class="form-check m-2 mb-2" id='wProfs' style="text-align: left;">
<input class="form-check-input inField checkInput tool" type="checkbox" name="tt" id="tt">
<label class="form-check-label" for="tt">Thieve's Tools</label>
<br>
<input class="form-check-input inField checkInput tool" type="checkbox" name="tdk" id="tdk">
<label class="form-check-label" for="tdk">Trap Disarming Kit</label>
<br>
<input class="form-check-input inField checkInput tool" type="checkbox" name="mi" id="mi">
<label class="form-check-label" for="mi">Musical Instruments</label>
<br>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="background-color: rgba(0,0,100,0.25); border: 1px solid black; border-radius: 10px;" class="mt-3 p-2">
<h3 style="text-align: center;">Notes</h3>
<hr>
<ul style="font-size: x-small;">
<li>When you go to print, if the print preview looks all funny hit cancel then ctrl+p to reopen the print dialog and it should be fixed.</li>
<li>When you save a character it will automatically send a file to your downloads folder.</li>
<li>To upload a character save, click on "Choose File", select the save file, then click "Open".</li>
<li>For both the "Weapon Proficiency" and "Feature" fields require you to press the "Add" button beside them in order to update.</li>
<li>If you acidentily added something you didn't mean to or made a mistake, mouse over the item on the preview. If you see a line through it, you can click on it and it will be removed.</li>
<li>The PDF generated by clicking "Save as PDF" will be formatted slightly diferently from the preview due to rendering issues. If you prefure the preview version over the generated PDF, you can save it via the print dialogue.</li>
</ul>
</div>
<!-- Column 2 - Preview Area-->
<div class="col mx-auto">
<div class="col m-3 mb-1 mx-auto" style="width: 8.5in;">
<h1 class="note" id="previewHeading">Preview:</h1>
</div>
<div id="previews">
<div id="pageArea" class="pageBorder shadow1 m-3 mt-1 mx-auto" style="height:11in; width: 8.5in;">
<!--Paper Size-->
<div class="centered ps-3 pe-3" style="height:10.5in; width: 8in;">
<!--Work Area-->
<!-- Character Info -->
<div class="mx-auto mt-3 row">
<div class="ASbackground col-8">
<h1 class="mt-2 AS1"><b id="charName"></b></h1>
<h4 id="raceLabel"></h4>
<h4 id="classLabel"></h4>
</div>
<div class="ASbackground col ms-2">
<h3 class="mt-3"><b>Base AC</b></h3>
<h1 class="AS1"><b id="baseAC"></b></h1>
</div>
</div>
<!-- Ability Scores -->
<div class="mt-3">
<div class="row p-3 mx-auto ASbackground" style="text-align: center;">
<div class="AS2 col m-1 p-2">
<h5>Strength</h5>
<div class="AS1">
<h1 class="AS1" id="strMod"></h1>
<h6 id="strScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Dexterity</h5>
<div class="AS1">
<h1 class="AS1" id="dexMod"></h1>
<h6 id="dexScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Constitution</h5>
<div class="AS1">
<h1 class="AS1" id="conMod"></h1>
<h6 id="conScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Intelligence</h5>
<div class="AS1">
<h1 class="AS1" id="intMod"></h1>
<h6 id="intScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Wisdom</h5>
<div class="AS1">
<h1 class="AS1" id="wisMod"></h1>
<h6 id="wisScore"></h6>
</div>
</div>
<div class="AS2 col m-1 p-2">
<h5>Charisma</h5>
<div class="AS1">
<h1 class="AS1" id="chaMod"></h1>
<h6 id="chaScore"></h6>
</div>
</div>
</div>
</div>
<div class="mt-3">
<div class="row mx-auto ASbackground p-2" style="text-align: center;">
<!-- <div class="col AS2 p-1 m-2">
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Spell Attack</h4>
<h1 id="spellAttack">8</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Spell Save</h4>
<h1 id="spellSave">8</h1>
</div>
<div class="AS1 p-1 m-2">
<h5 class="mt-2">Spell Casting Modifier</h5>
<h1 id="spellMod">8</h1>
</div>
</div> -->
<div class="col AS2 p-1 m-2">
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Movement Speed</h4>
<hr class="ms-3 me-3">
<h1 id="moveSpeed">30 ft</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Jump Distance</h4>
<hr class="ms-3 me-3">
<h1 id="jumpDist">15 ft</h1>
</div>
<div class="AS1 p-1 m-2">
<h4 class="mt-2">Carrying Capacity</h4>
<hr class="ms-3 me-3">
<h1 id="carryCap">150 lbs</h1>
</div>
</div>
<div class="col AS2 p-1 m-2">
<h4 class="mt-2">Features & Trates</h4>
<hr class="ms-3 me-3">
<div id="featsDiv" style="text-align: justify;">
<ul id="featsList">
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="pageArea2" class="pageBorder shadow1 m-3 mt-1 mx-auto" style="height:11in; width: 8.5in;">
<!--Paper Size-->
<div class="centered ps-3 pe-3" style="height:10.5in; width: 8in;">
<!--Work Area-->
<!-- Proficiencies -->
<div class="row mt-3 mx-auto">
<div class="ASbackground mx-auto pb-3 row">
<h1 class="mt-2"><b>Proficiencies</b></h1>
<div class="col m-1 AS1">
<h3 class="mt-3">Skill Proficiencies</h3>
<hr>
<div class="form-check m-2 mb-3" style="text-align: left;">
<input style="display: inline-block;" class="form-check-input skillProfCheck checkInput" type="checkbox" id="AcrobaticsRad" name="AcrobaticsRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='AcrobaticsExp' id='AcrobaticsExpId' prevVal="off">
<label class="form-check-label" for="AcrobaticsRad">Acrobatics (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="AnimalHandlingRad" name="AnimalHandlingRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='AnimalHandlingExp' id='AnimalHandlingExpId' prevVal="off">
<label class="form-check-label" for="AnimalHandlingRad">Animal Handling (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="ArcanaRad" name="ArcanaRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' name='ArcanaExp' id='ArcanaExpId' prevVal="off">
<label class="form-check-label" for="ArcanaRad">Arcana (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="AthleticsRad" name="AthleticsRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='AthleticsExpId' prevVal="off">
<label class="form-check-label" for="AthleticsRad">Athletics (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="DeceptionRad" name="DeceptionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='DeceptionExpId' prevVal="off">
<label class="form-check-label" for="DeceptionRad">Deception (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="HistoryRad" name="HistoyRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='HistoryExpId' prevVal="off">
<label class="form-check-label" for="HistoryRad">History (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="InsightRad" name="InsightRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='InsightExpId' prevVal="off">
<label class="form-check-label" for="InsightRad">Insight (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="IntimidationRad" name="IntimidationRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='IntimidationExpId' prevVal="off">
<label class="form-check-label" for="IntimidationRad">Intimidation (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="InvestigationRad" name="InvestigationRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='InvestigationExpId' prevVal="off">
<label class="form-check-label" for="InvestigationRad">Investigation (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="MedicineRad" name="MedicineRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='MedicineExpId' prevVal="off">
<label class="form-check-label" for="MedicineRad">Medicine (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="NatureRad" name="NatureRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='NatureExpId' prevVal="off">
<label class="form-check-label" for="NatureRad">Nature (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PerceptionRad" name="PerceptionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PerceptionExpId' prevVal="off">
<label class="form-check-label" for="PerceptionRad">Perception (WIS)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PerformanceRad" name="PerformanceRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PerformanceExpId' prevVal="off">
<label class="form-check-label" for="PerformanceRad">Performance (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="PersuasionRad" name="PersuasionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='PersuasionExpId' prevVal="off">
<label class="form-check-label" for="PersuasionRad">Persuasion (CHA)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="ReligionRad" name="ReligionRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='ReligionExpId' prevVal="off">
<label class="form-check-label" for="ReligionRad">Religion (INT)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="SleightOfHandRad" name="SleightOfHandRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='SleightOfHandExpId' prevVal="off">
<label class="form-check-label" for="SleightOfHandRad">Sleight of Hand (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="StealthRad" name="StealthRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='StealthExpId' prevVal="off">
<label class="form-check-label" for="StealthRad">Stealth (DEX)</label>
<br>
<input class="form-check-input skillProfCheck checkInput" type="checkbox" id="SurvivalRad" name="SurvivalRad" value="something">
<input class='form-check-input ms-1 me-3 checkInput expert d-none' type='radio' id='SurvivalExpId' prevVal="off">
<label class="form-check-label" for="SurvivalRad">Survival (WIS)</label>
</div>
</div>
<div class="col m-1 AS1">
<h3 class="mt-3">Equipment Proficiencies</h3>
<div class="AS2 mt-2 p-2" id="armorProfDiv">
<h5 class="mt-2">Armor</h5>
<hr>
<ul id="armorProf" style="text-align: justify;">
</ul>
</div>
<div class="AS2 p-2 mt-2" id="weaponProfDiv">
<h5 class="mt-2">Weapons</h5>
<hr>
<ul id="wpnProf" style="text-align: justify;">
</ul>
</div>
<div class="AS2 p-2 mt-2 mb-2" id="toolProfDiv">
<h5 class="mt-2">Tools</h5>
<hr>
<ul id="toolProf" style="text-align: justify;">
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="charUploadDiv"></div>
</body>
<!-- <script type="module">
// import { jsPDF } from "jspdf";
import { jsPDF } from "https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js";
</script> -->
<script>
const { jsPDF } = window.jspdf;
$(document).ready(function () {
$(".subraceMenu").hide();
var hasSubraces = ["Elf","Half-Elf","Drow","Tiefling","Dwarf","Halfling","Gnome","Dragonborn"];
var noSubraces = ["Human","Half-Orc","Githyanki"]
var profs = ['Acrobatics','AnimalHandling','Arcana','Athletics','Deception','History','Insight','Intimidation','Investigation','Medicine','Nature','Perception','Performance','Persuasion','Religion','SleightOfHand','Stealth','Survival']
var abilities = ['str','dex','con','int','wis','cha']
var showExp = false;
function char(){
this.abilityScore = {str:'', dex:"", con:"", int:"", wis:"", cha:""};
this.race = "";
this.classDescription = "";
this.FeaturesAndTrates = [];
this.armorProfs = [];
this.weaponProfs = [];
this.toolProfs = [];
this.name = "";
this.abilityProfs = [];
this.abilityExpertise = [];
this.abilityProfs1 = [];
this.abilityExpertise1 = [];
this.baseRase = '';
this.subRace = '';
this.lvl = 0;
}
const charSave = new char;
// charSave.classDescription = "";
charSave.armorProfs = [1];
charSave.weaponProfs = [1];
charSave.toolProfs = [1];
charSave.abilityExpertise = [];
charSave.abilityProfs = [];
charSave.race = $(".raceField").val();
charSave.FeaturesAndTrates = [1];
loadFileAsText = function (){
var fileToLoad = document.getElementById("charUpload").files[0];
var fileReader = new FileReader();
fileReader.onload = function(fileLoadedEvent){
var textFromFileLoaded = fileLoadedEvent.target.result;
// console.log(textFromFileLoaded);
document.getElementById("charUploadDiv").value = textFromFileLoaded;
};
fileReader.readAsText(fileToLoad, "UTF-8");
}
showExpertise = function() {
for (let i = 0; i<profs.length; i++) {
$("#"+profs[i]+"ExpId").removeClass('d-none');
}
}
hideExpertise = function () {
for (let i = 0; i<profs.length; i++) {
$("#"+profs[i]+"ExpId").addClass('d-none');
}
};
var exp = [];
updateToolMenu = function(){
for (let i = 0; i<charSave.toolProfs.length-1; i++){
var target = charSave.toolProfs[i+1];
if (target == "Thieve's Tools") {
$("#tt").prop('checked', true);
} else if (target == "Trap Disarming Kits") {
$("#tdk").prop('checked', true);
} else if (target == "Musical Instruments") {
$("#mi").prop('checked', true);
}
}
$("#toolProf").empty();
for (let i = 1; i<charSave.toolProfs.length; i++) {
$("#toolProf").append("<li class='toolLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.toolProfs[i]+"</li>");
}
}
loadCharacter = function () {
loadFileAsText()
setTimeout(function(){
// console.log("Div Value: "+$("#charUploadDiv").val())
var uploadedCharJSON = $("#charUploadDiv").val()
// console.log("uploadedCharJSON: "+uploadedCharJSON)
var parsedCharJSON = JSON.parse(uploadedCharJSON);
// console.log(parsedCharJSON);
// console.log(parsedCharJSON.name)
charSave.armorProfs = parsedCharJSON.armorProfs;
charSave.weaponProfs = parsedCharJSON.weaponProfs;
charSave.toolProfs = parsedCharJSON.toolProfs;
charSave.abilityExpertise1 = parsedCharJSON.abilityExpertise;
charSave.abilityProfs1 = parsedCharJSON.abilityProfs;
charSave.abilityScore = parsedCharJSON.abilityScore;
charSave.race = parsedCharJSON.race;
charSave.FeaturesAndTrates = parsedCharJSON.FeaturesAndTrates;
charSave.classDescription = parsedCharJSON.classDescription;
charSave.name = parsedCharJSON.name;
charSave.baseRase = parsedCharJSON.baseRase;
charSave.subRace = parsedCharJSON.subRace;
// console.log(charSave.abilityProfs1);
// console.log(charSave.abilityExpertise1);
$("#charName").text(charSave.name);
$("#Name").val(charSave.name);
$("#charRace").val(parsedCharJSON.baseRase);
if (hasSubraces.includes(charSave.baseRase)){
$("#subraceHeader").show();
}
$("#"+parsedCharJSON.baseRase+"Menu").show();
$("#"+parsedCharJSON.baseRase+"Menu").val(charSave.subRace);
$("#str").val(charSave.abilityScore['str']);
$("#dex").val(charSave.abilityScore['dex']);
$("#con").val(charSave.abilityScore['con']);
$("#int").val(charSave.abilityScore['int']);
$("#wis").val(charSave.abilityScore['wis']);
$("#cha").val(charSave.abilityScore['cha']);
if (parsedCharJSON.classDescription.includes("Bard") || charSave.classDescription.includes("Rogue")) {
showExpertise();
} else {
hideExpertise();
}
if (parsedCharJSON.classDescription.includes("-")){
// console.log(cMenus);
let text = parsedCharJSON.classDescription;
let arr = text.split(' ')
let countDashes = text.split("-").length-1;
for (let i = 0; i<countDashes; i++) {
addClass()
}
for (let i = 0; i<cMenus; i++) {
if (i == 0){
// console.log(arr);
$("#classSubMenu"+(i+1)).val(arr[0])
$("#lvl"+(i+1)).val(arr[1][1]);
// console.log("lvl: "+arr[(i*4)+1][1])
charSave.lvl = charSave.lvl+parseInt(arr[(i*4)+1][1]);
} else {
// console.log(arr[i*4]);
$("#classSubMenu"+(i+1)).val(arr[i*4])
$("#lvl"+(i+1)).val(arr[(i*4)+1][1]);
// console.log("lvl: "+arr[(i*4)+1][1])
charSave.lvl = charSave.lvl+parseInt(arr[(i*4)+1][1]);
}
}
}
for (let i = 0; i<charSave.abilityProfs1.length; i++){
$("#"+charSave.abilityProfs1[i]+"Rad").attr('checked', true);
}
for (let i = 0; i<charSave.abilityExpertise1.length; i++){
$("#"+charSave.abilityExpertise1[i]+"ExpId").attr('checked', true);
}
for (let i = 0; i<charSave.armorProfs.length-1; i++){
// console.log(charSave.armorProfs[i+1]);
if (charSave.armorProfs[i+1] != "Shields"){
let target = charSave.armorProfs[i+1].replace(" Armor", "");
$("#"+target+"Prof").attr('checked', true);
} else {
let target = charSave.armorProfs[i+1];
$("#"+target+"Prof").attr('checked', true);
}
}
for (let i = 0; i<charSave.weaponProfs.length-1; i++){
// console.log(charSave.weaponProfs[i+1]);
let target = charSave.weaponProfs[i+1].replace(" Weapons", "")
$("#"+target).attr('checked', true);
}
updateToolMenu();
updatePreview();
},50)
// charSave.abilityExpertise = exp;
}
var cMenus = 1;
addClass = function() {
cMenus++
// console.log("Class Menu Count: "+cMenus);
$("#classesMenu").append('<div class="row m-1" id="cMen'+cMenus+'"><select onchange="updatePreview()" class="col form-select inField classMenu mb-2" id="classSubMenu'+cMenus+'"><option>Barbarian</option><option>Bard</option><option>Cleric</option><option>Druid</option><option>Fighter</option><option>Monk</option><option>Paladin</option><option>Ranger</option><option>Rogue</option><option>Sorcerer</option><option>Warlock</option><option>Wizard</option></select><input type="number" id="lvl'+cMenus+'" name="lvl" min="1" max="20" class="inField col-3 mb-2 ms-1" onclick="updatePreview()" value="1"></div>')
updateClassDescription();
updatePreview();
}
updateClassDescription = function(){
var menus = $(".classMenu");
charSave.classDescription = '';
// console.log(menus.length);
for (let i = 0; i<menus.length; i++) {
if (i >= 1) {
charSave.classDescription = charSave.classDescription + " - " + $("#classSubMenu"+(i+1)).val() + " (" + $("#lvl"+(i+1)).val() + ") ";
} else {
charSave.classDescription = charSave.classDescription+ $("#classSubMenu"+(i+1)).val() + " (" + $("#lvl"+(i+1)).val() + ") ";
}
}
if (charSave.classDescription.includes("Bard") || charSave.classDescription.includes("Rogue")) {
showExpertise();
} else {
hideExpertise();
}
}
removeClass = function() {
$("#cMen" + cMenus).remove();
cMenus--
if (cMenus < 1) {
cMenus = 1;
}
updateClassDescription();
updatePreview();
}
$(".classMenu").change( function () {
updateClassDescription();
})
mouseOverLi = function(itm) {
$(itm).css("text-decoration","line-through");
$(itm).append(" ⦻");
}
mouseLeaveLi = function(itm) {
$(itm).css("text-decoration","none");
var txt = $(itm).text();
$(itm).text(txt.split(" ⦻")[0]);
}
clickLi = function(itm) {
if ($(itm).hasClass("wpnLabel")) {
var foritm = $(itm).attr("for");
console.log(foritm);
$("#" + foritm).remove()
$("." + foritm).remove()
}
if ($(itm).hasClass("armorLi")) {
console.log("Raw Text: "+$(itm).text());
// console.log("Altered Text: "+idStr);
if ($(itm).text() != "Shields ⦻") {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
var idStr = target.replace(" Armor", "");
$("#"+(idStr)+"Prof").prop('checked', false);
let x = charSave.armorProfs.splice(i,1);
}
}
} else {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
$("#"+(target)+"Prof").prop('checked', false);
}
}
}
} else if ($(itm).hasClass("wpnLi")) {
target = ($(itm).text().replace(" ⦻", ""));
console.log("target = " + target);
for (let i = 1; i<charSave.weaponProfs.length; i++) {
if (charSave.weaponProfs[i] == target) {
var idStr = target.replace(" Weapons", "");
$("#"+(idStr)).prop('checked', false);
let x = charSave.weaponProfs.splice(i,1);
// console.log("i = "+ i + " list = "+weapon);
}
}
} else if ($(itm).hasClass("toolLi")) {
target = $(itm).text().replace(" ⦻","")
console.log("Target: ",target);
if (target == "Thieve's Tools") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#tt").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
} else if (target == "Trap Disarming Kits") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#tdk").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
} else if (target == "Musical Instruments") {
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
$("#mi").prop('checked', false);
let x = charSave.toolProfs.splice(i,1);
}
}
}
} else if ($(itm).hasClass("featItm")) {
target = ($(itm).text().replace(" ⦻", ""));
for (let i = 1; i<charSave.FeaturesAndTrates.length; i++) {
if (charSave.FeaturesAndTrates[i] == target) {
let x = charSave.FeaturesAndTrates.splice(charSave.FeaturesAndTrates.indexOf(target),1);
}
}
}
$(itm).remove();
updatePreview();
}
addWeapon = function() {
charSave.weaponProfs.push($("#addWeapons").val());
updatePreview();
}
addFeat = function() {
$("#featsList").append("<li class='listItem featItm' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>" + $("#addFeat").val() + "</li>");
// $("#featsDiv").append("<br>");
charSave.FeaturesAndTrates.push($("#addFeat").val());
}
updateFeats = function () {
$("#featsList").empty();
for (let i = 1; i<charSave.FeaturesAndTrates.length; i++){
$("#featsList").append("<li class='listItem featItm' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>" + charSave.FeaturesAndTrates[i] + "</li>");
// $("#featsDiv").append("<br>");
}
}
$(".raceField").change(function() {
// $(".subraceMenu").hide();
if(hasSubraces.includes($(this).val())) {
$(".subraceMenu").hide();
$("#subraceHeader").show();
$("#"+$(this).val()+"Menu").show();
console.log("Has Subrace")
charSave.race = $("#"+$(this).val()+"Menu").val();
$("#raceLabel").text(charSave.race);
} else if(noSubraces.includes($(this).val())) {
$(".subraceMenu").hide();
charSave.race = $(this).val();
$("#raceLabel").text(charSave.race);
} else {
charSave.race = $(this).val();
$("#raceLabel").text(charSave.race);
};
console.log("Race Changed to "+charSave.race);
if($(this).val() == 'Dwarf' || $(this).val() == 'Gnome' || $(this).val() == 'Halfling') {
$("#moveSpeed").text("25 ft");
} else if(charSave.race == "Wood Half-Elf" || charSave.race == "Wood Elf"){
$("#moveSpeed").text("35 ft");
} else {
$("#moveSpeed").text("30 ft");
};
});
updateCharacter = function() {
charSave.name = $("#charName").text();
for (let i=0; i<abilities.length; i++){
// console.log(abilities[i])
charSave.abilityScore[abilities[i]] = $("#"+abilities[i]).val();
}
// console.log(charSave.abilityScore);
}
updatePreview = function() {
charSave.baseRase = $("#charRace").val();
charSave.subRace = charSave.race;
// console.log("Div Value: "+$("#charUploadDiv").val())
var jumpDistance;
var carryCap;
updateClassDescription();
updateFeats();
if($('#charRace').val() == 'Dwarf' || $('#charRace').val() == 'Gnome' || $('#charRace').val() == 'Halfling') {
$("#moveSpeed").text("25 ft");
} else if(charSave.race == "Wood Half-Elf" || charSave.race == "Wood Elf"){
$("#moveSpeed").text("35 ft");
} else {
$("#moveSpeed").text("30 ft");
};
$("#raceLabel").text(charSave.race);
$("#classLabel").text(charSave.classDescription);
for (let i = 0; i<abilities.length; i++) {
var id = abilities[i];
var score = $("#"+abilities[i]).val();
$("#"+id.toString()+"Score").text(score);
var mod = (score-10)/2;
var mod = Math.floor(mod);
if (mod < 0) {
$("#"+id.toString()+"Mod").text(mod.toString());
} else {
$("#"+id.toString()+"Mod").text("+"+mod.toString());
}
}
if ($("#Name").val() == "") {
$("#charName").text("Tav");
$("#printBtn").attr('onclick', 'printDiv("Tav")')
charSave.name = "Tav";
} else {
$("#charName").text($("#Name").val());
$("#printBtn").attr('onclick', 'printDiv("'+$("#Name").val()+'")')
charSave.name = $("#Name").val();
}
jumpDistance = 15 + (3*$("#strMod").text())
if (jumpDistance < 15) {
jumpDistance = 15;
}
$("#jumpDist").text(jumpDistance + " ft");
carryCap = 80+(20*$("#str").val());
$("#carryCap").text(carryCap + " lbs");
var dexMod = $("#dex").val()
dexMod = (dexMod-10)/2;
var baseAC = 10+Math.floor(dexMod);
$("#baseAC").text(baseAC.toString());
// console.log("--- Preview Updated ---")
charSave.abilityProfs = [];
charSave.abilityExpertise = [];
for (let i = 0; i<profs.length; i++) {
var skill = profs[i];
if ($("#"+skill+"Rad").is(':checked')) {
// console.log(skill+" is checked")
$("#"+skill+"Rad").attr("checked", true);
charSave.abilityProfs.push(skill);
} else {
// console.log(skill+" is unchecked")
$("#"+skill+"Rad").attr("checked", false);
// charSave.abilityProfs.splice(charSave.abilityProfs.indexOf(skill),i)
}
if ($("#"+skill+"ExpId").is(':checked')) {
// console.log(skill+" is checked")
$("#"+skill+"EspId").attr("checked", true);
charSave.abilityExpertise.push(skill);
} else {
// console.log(skill+" is unchecked")
$("#"+skill+"ExpId").attr("checked", false);
// charSave.abilityProfs.splice(charSave.abilityProfs.indexOf(skill),i)
}
}
$("#armorProf").empty();
for (let i = 1; i<charSave.armorProfs.length; i++) {
$("#armorProf").append("<li class='armorLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.armorProfs[i]+"</li>");
}
$("#wpnProf").empty();
for (let i = 1; i<charSave.weaponProfs.length; i++) {
$("#wpnProf").append("<li class='wpnLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.weaponProfs[i]+"</li>");
}
$("#toolProf").empty();
for (let i = 1; i<charSave.toolProfs.length; i++) {
$("#toolProf").append("<li class='toolLi' onclick='clickLi(this)' onmouseover='mouseOverLi(this)' onmouseout='mouseLeaveLi(this)'>"+charSave.toolProfs[i]+"</li>");
}
updateToolMenu();
updateCharacter();
// console.log(charSave);
}
$(".inField").change(function() {
var target = '';
if ($(this).attr('id') == 'hideArmor'){
if ($(this).prop('checked') == true) {
$("#armorProfDiv").hide();
} else {
$("#armorProfDiv").show();
}
} else if ($(this).attr('id') == 'hideWeapons'){
if ($(this).prop('checked') == true) {
$("#weaponProfDiv").hide();
} else {
$("#weaponProfDiv").show();
}
} else if ($(this).attr('id') == 'hideTools'){
if ($(this).prop('checked') == true) {
$("#toolProfDiv").hide();
} else {
$("#toolProfDiv").show();
}
};
if ($(this).hasClass("checkInput") && $(this).prop('checked') == true) {
if ($(this).hasClass("armor")) {
// console.log("Is Armor")
if ($(this).attr('name') != "Shields") {
charSave.armorProfs.push($(this).attr('name')+" Armor");
} else {
charSave.armorProfs.push($(this).attr('name'));
}
}
if ($(this).hasClass("wpn")) {
charSave.weaponProfs.push($(this).attr('name')+" Weapons");
}
if ($(this).hasClass("tool")) {
if ($(this).attr('name') == "tt") {
charSave.toolProfs.push("Thieve's Tools");
} else if ($(this).attr('name') == "tdk") {
charSave.toolProfs.push("Trap Disarming Kits");
} else if ($(this).attr('name') == "mi") {
charSave.toolProfs.push("Musical Instruments");
}
}
} else {
if ($(this).hasClass("armor")) {
// console.log("Is Armor")
if ($(this).attr('name') != "Shields") {
target = ($(this).attr('name')+" Armor");
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
}
}
} else {
target = ($(this).attr('name'));
for (let i = 1; i<charSave.armorProfs.length; i++) {
if (charSave.armorProfs[i] == target) {
let x = charSave.armorProfs.splice(i,1);
}
}
}
}
if ($(this).hasClass("wpn")) {
target = ($(this).attr('name')+" Weapons");
// console.log("target = " + target);
for (let i = 1; i<charSave.weaponProfs.length; i++) {
if (charSave.weaponProfs[i] == target) {
let x = charSave.weaponProfs.splice(i,1);
}
}
}
if ($(this).hasClass("tool")) {
if ($(this).attr('name') == "tt") {
target = "Thieve's Tools";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
} else if ($(this).attr('name') == "tdk") {
target = "Trap Disarming Kits";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
} else if ($(this).attr('name') == "mi") {
target = "Musical Instruments";
for (let i = 1; i<charSave.toolProfs.length; i++) {
if (charSave.toolProfs[i] == target) {
console.log("Target:",target," i:",i," Index of Target:",charSave.toolProfs.indexOf(target));
console.log(charSave.toolProfs)
let x = charSave.toolProfs.splice(i,1);
console.log(charSave.toolProfs)
}
}
}
}
}
// console.log("inField Updated");
updatePreview()
})
$(".checkInput").change(function() {
// console.log($(this).attr('id'))
$(this).attr("checked", true);
updatePreview();
});
$("#charUpload").change(function(){
loadCharacter();
});
$("[type='radio']").on('click', function () {
if ($(this).attr('prevVal') == 'on') {
$(this).attr('prevVal','off')
$(this).prop('checked', false);
$(this).attr('checked', false);
} else {
$(this).attr('prevVal','on')
$(this).prop('checked', true);
$(this).attr('checked', true);
}
});
updatePreview()
saveCharacter = function() {
const charSaveJSON = JSON.stringify(charSave);
// console.log("JSON-ified charSave: "+ charSaveJSON);
function downloadString(text, fileType, fileName) {
var blob = new Blob([text], { type: fileType });
var a = document.createElement('a');
a.download = fileName;
a.href = URL.createObjectURL(blob);
a.dataset.downloadurl = [fileType, a.download, a.href].join(':');
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function() { URL.revokeObjectURL(a.href); }, 1500);
}
// downloadString("a,b,c\n1,2,3", "text/csv", "myCSV.csv")
downloadString(charSaveJSON, "text/plain", charSave.name+" - lvl("+charSave.lvl+").txt")
}
var doc = new jsPDF();
var specialElementHandlers = {
'#editor': function (element, renderer) {
return true;
}
};
//Create PDf from HTML...
CreatePDFfromHTML = function () {
$(".pageBorder").css("border-color", "white");
$(".AS1").addClass("pdfFormat");
$(".AS2").addClass("pdfFormat");
$(".ASBackground").addClass("pdfFormat");
var HTML_Width = $("#pageArea").width();
var HTML_Height = $("#pageArea").height();
var canvas_image_width = HTML_Width;
var canvas_image_height = HTML_Height;
var top_left_margin = 0;
asRatio = 11/8.5;
var PDF_Width = HTML_Width + (top_left_margin * 2);
var PDF_Height = HTML_Height + (top_left_margin * 2);
var totalPDFPages = 1;
console.log("HTML Width: "+HTML_Width+" HTML Height: "+HTML_Height);
console.log("PDF Width: "+PDF_Width+" PDF Height: "+PDF_Height);
var len = 2; //$x(".//body/div/div").length
var divIds = ["#pageArea","#pageArea2"]
var pdf = new jsPDF('p', 'pt',[PDF_Width, PDF_Height]);
var position = 0;
// Hide
for (let i = 1;i <= len; i++){
html2canvas(document.querySelector(divIds[i-1]),
{dpi: 600, // Set to 300 DPI
scale: 5, // Adjusts your resolution
height: PDF_Height,
width: PDF_Width
}).then(canvas => {
// pdf.addImage(canvas.toDataURL("images/png", 1), 'PNG', 0,position, 210, 295);
var imgData = canvas.toDataURL("image/jpeg", 1.0);
pdf.addImage(imgData, 'PNG', top_left_margin, top_left_margin, canvas_image_width, canvas_image_height);
if (i == len){
// pdf.save('sample-file.pdf');
window.open(pdf.output('bloburl'));
}else{
pdf.addPage();
}
});
}
$(".pageBorder").css("border-color", "black");
$(".AS1").removeClass("pdfFormat");
$(".AS2").removeClass("pdfFormat");
$(".ASBackground").removeClass("pdfFormat");
}
});
</script>
</html>