Obsidian Portal
Menu
Sign In / Create Account
JavaScript is currently disabled. Obsidian Portal has a lot of really cool features that use JavaScript. You should check them out. We think you'll have a much more enjoyable experience.
Home
Campaigns
Games Nearby
Plans
Community
Help
Resources
Exalted - Terrestrial
Author:
ChainsawXIV
Slug:
chainsawxiv_exalted_terrestrial
Type:
GameCharacter
System:
Exalted
DST Source Code
HTML Template
<div class="wrapper"> <div class="tab_bar"> <span class="tab" onclick="chainsawxiv_exalted_terrestrial_tabClick(this,'sheet');"> CHARACTER </span> <span class="tab" onclick="chainsawxiv_exalted_terrestrial_tabClick(this,'bio');"> BIOGRAPHY </span> </div> <div class="main page_sheet" style="display:block;"> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-left.png" class="corner_top_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-right.png" class="corner_top_right" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-left.png" class="corner_bottom_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-right.png" class="corner_bottom_right" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-bottom.png" class="brass_bottom" /> <div class="page_head"> <div class="section_head"> <span class="name dsf dsf_name"></span> </div> <span class="align_right dsf dsf_type typev"></span> • <span class="align_left dsf dsf_campaign"></span> </div> <div class="section_head">ATTRIBUTES</div> <div class="section"> <div class="column column_spacing"> Strength<span class="readonly pipsRange_10 dsf dsf_strength"></span><br /> Dexterity<span class="readonly pipsRange_10 dsf dsf_dexterity"></span><br /> Stamina<span class="readonly pipsRange_10 dsf dsf_stamina"></span><br /> </div> <div class="column column_spacing"> Charisma<span class="readonly pipsRange_10 dsf dsf_charisma"></span><br /> Manipulation<span class="readonly pipsRange_10 dsf dsf_manipulation"></span><br /> Appearance<span class="readonly pipsRange_10 dsf dsf_appearance"></span><br /> </div> <div class="column"> Perception<span class="readonly pipsRange_10 dsf dsf_perception"></span><br /> Intelligence<span class="readonly pipsRange_10 dsf dsf_intelligence"></span><br /> Wits<span class="readonly pipsRange_10 dsf dsf_wits"></span><br /> </div> </div> <div class="section_head">ABILITIES</div> <div class="section"> <div class="column column_spacing"> <b>AIR</b><br /> <span class="readonly check dsf dsf_linguistics_favored"></span>Linguistics<span class="readonly pipsRange_10 dsf dsf_linguistics"></span><br /> <span class="readonly check dsf dsf_lore_favored"></span>Lore<span class="readonly pipsRange_10 dsf dsf_lore"></span><br /> <span class="readonly check dsf dsf_occult_favored"></span>Occult<span class="readonly pipsRange_10 dsf dsf_occult"></span><br /> <span class="readonly check dsf dsf_stealth_favored"></span>Stealth<span class="readonly pipsRange_10 dsf dsf_stealth"></span><br /> <span class="readonly check dsf dsf_thrown_favored"></span>Thrown<span class="readonly pipsRange_10 dsf dsf_thrown"></span><br /> <br /> <b>WATER</b><br /> <span class="readonly check dsf dsf_bureaucracy_favored"></span>Bureaucracy<span class="readonly pipsRange_10 dsf dsf_bureaucracy"></span><br /> <span class="readonly check dsf dsf_investigation_favored"></span>Investigation<span class="readonly pipsRange_10 dsf dsf_investigation"></span><br /> <span class="readonly check dsf dsf_larceny_favored"></span>Larceny<span class="readonly pipsRange_10 dsf dsf_larceny"></span><br /> <span class="readonly check dsf dsf_martial_arts_favored"></span>Martial Arts<span class="readonly pipsRange_10 dsf dsf_martial_arts"></span><br /> <span class="readonly check dsf dsf_sail_favored"></span>Sail<span class="readonly pipsRange_10 dsf dsf_sail"></span><br /> </div> <div class="column column_spacing"> <b>EARTH</b><br /> <span class="readonly check dsf dsf_awareness_favored"></span>Awareness<span class="readonly pipsRange_10 dsf dsf_awareness"></span><br /> <span class="readonly check dsf dsf_craft_favored"></span>Craft<span class="readonly pipsRange_10 dsf dsf_craft"></span><br /> <span class="readonly check dsf dsf_integrity_favored"></span>Integrity<span class="readonly pipsRange_10 dsf dsf_integrity"></span><br /> <span class="readonly check dsf dsf_resistance_favored"></span>Resistance<span class="readonly pipsRange_10 dsf dsf_resistance"></span><br /> <span class="readonly check dsf dsf_war_favored"></span>War<span class="readonly pipsRange_10 dsf dsf_war"></span><br /> <br /> <b>WOOD</b><br /> <span class="readonly check dsf dsf_archery_favored"></span>Archery<span class="readonly pipsRange_10 dsf dsf_archery"></span><br /> <span class="readonly check dsf dsf_medicine_favored"></span>Medicine<span class="readonly pipsRange_10 dsf dsf_medicine"></span><br /> <span class="readonly check dsf dsf_performance_favored"></span>Performance<span class="readonly pipsRange_10 dsf dsf_performance"></span><br /> <span class="readonly check dsf dsf_ride_favored"></span>Ride<span class="readonly pipsRange_10 dsf dsf_ride"></span><br /> <span class="readonly check dsf dsf_survival_favored"></span>Survival<span class="readonly pipsRange_10 dsf dsf_survival"></span><br /> </div> <div class="column"> <b>FIRE</b><br /> <span class="readonly check dsf dsf_athletics_favored"></span>Athletics<span class="readonly pipsRange_10 dsf dsf_athletics"></span><br /> <span class="readonly check dsf dsf_dodge_favored"></span>Dodge<span class="readonly pipsRange_10 dsf dsf_dodge"></span><br /> <span class="readonly check dsf dsf_melee_favored"></span>Melee<span class="readonly pipsRange_10 dsf dsf_melee"></span><br /> <span class="readonly check dsf dsf_presence_favored"></span>Presence<span class="readonly pipsRange_10 dsf dsf_presence"></span><br /> <span class="readonly check dsf dsf_socialize_favored"></span>Socialize<span class="readonly pipsRange_10 dsf dsf_socialize"></span><br /> </div> </div> <div class="section"> <div class="column column_spacing"> <div class="section_head">CRAFTS<a class="interface listAdd" title="Add Craft" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_crafts')[0].addItem();">+</a></div> <div class="list_crafts listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_craft_type_ type5"></span><span class="readonly pipsRange_5 dsf dsf_craft_value_">0</span><br /> </div> </div> </div> </div> <div class="column column_spacing"> <div class="section_head">SPECIALTIES<a class="interface listAdd" title="Add Specialty" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_specialties')[0].addItem();">+</a></div> <div class="list_specialties listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_specialty_type_ type3"></span><span class="readonly pipsRange_3 dsf dsf_specialty_value_">0</span><br /> </div> </div> </div> </div> <div class="column"> <div class="section_head">LANGUAGES<a class="listAdd interface" title="Add Language" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_languages')[0].addItem();">+</a></div> <div class="list_languages listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_language_ typef"></span><br /> </div> </div> </div> </div> </div> <div class="section"> <div class="column column_spacing"> <div class="section_head">VIRTUES</div> Compassion<span class="readonly pipsRange_5 dsf dsf_compassion"></span><br /> Conviction<span class="readonly pipsRange_5 dsf dsf_conviction"></span><br /> Temperance<span class="readonly pipsRange_5 dsf dsf_temperance"></span><br /> Valor<span class="readonly pipsRange_5 dsf dsf_valor"></span><br /> </div> <div class="column column_spacing"> <div class="section_head">MERITS<a class="listAdd interface" title="Add Merit" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_merits')[0].addItem();">+</a></div> <div class="list_merits listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_merit_ typef"></span><br /> </div> </div> </div> </div> <div class="column"> <div class="section_head">FLAWS<a class="listAdd interface" title="Add Flaw" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_flaws')[0].addItem();">+</a></div> <div class="list_flaws listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_flaw_ typef"></span><br /> </div> </div> </div> </div> </div> <div class="section_head">BACKGROUNDS<a class="listAdd interface" title="Add Background" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_backgrounds')[0].addItem();">+</a></div> <div class="section"> <div class="list_backgrounds listColumns_3"> <div class="template"> <div class="has_tooltip"> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf type5 dsf dsf_background_type_"></span><span class="readonly pipsRange_5 dsf dsf_background_value_">0</span><br /> <span class="readonly area dsf dsf_background_tootip_ is_tooltip button_float"></span> </div> </div> </div> </div> <div class="section_head">CHARMS<a class="listAdd interface" title="Add Charm" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_charms')[0].addItem();">+</a></div> <div class="section"> <div class="list_charms listColumns_3"> <div class="template"> <div class="has_tooltip"> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_charm_name_ typef"></span><br /> <span class="readonly area dsf dsf_charm_tootip_ is_tooltip button_float"></span> </div> </div> </div> </div> <div class="section_head">SORCERY<a class="listAdd interface" title="Add Sorcery" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_sorcery')[0].addItem();">+</a></div> <div class="section"> <div class="list_sorcery listColumns_3"> <div class="template"> <div class="has_tooltip"> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_sorcery_ typef"></span><br /> <span class="readonly area dsf dsf_sorcery_tootip_ is_tooltip button_float"></span> </div> </div> </div> </div> <div class="section_head">COMBOS<a class="listAdd interface" title="Add Combo" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_combos')[0].addItem();">+</a></div> <div class="section"> <div class="list_combos listColumns_1"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf typew dsf dsf_combo_type_"></span><br /> </div> </div> </div> </div> <div class="section"> <div class="column column_spacing"> <div class="section_head">MISCELLANEOUS</div> Willpower<span class="readonly pipsRange_10 dsf dsf_willpower"></span><br /> Essence<span class="readonly pipsRange_10 dsf dsf_essence"></span><br /> Personal Pool: <span class="dsf dsf_personal_pool typer"></span><br /> Peripheral Pool: <span class="dsf dsf_peripheral_pool typer"></span><br /> </div> <div class="column column_spacing"> <div class="section_head">DEFENSES</div> Soak: <span class="dsf dsf_soak typer" style="width:106px;"></span><br /> Hardness: <span class="dsf dsf_hardness typer" style="width:106px;"></span><br /> Physical DVs: <span class="dsf dsf_dvs typer" style="width:106px;"></span><br /> Mental DVs: <span class="dsf dsf_mdvs typer" style="width:106px;"></span><br /> </div> <div class="column"> <div class="section_head">HEALTH</div> -0 Levels<span class="readonly pipsRange_10 dsf dsf_0health"></span><br /> -1 Levels<span class="readonly pipsRange_10 dsf dsf_1health"></span><br /> -2 Levels<span class="readonly pipsRange_10 dsf dsf_2health"></span><br /> -4 Levels<span class="readonly pipsRange_10 dsf dsf_4health"></span><br /> </div> </div> <div class="section_head">EQUIPMENT<a class="listAdd interface" title="Add Equipment" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_equipment')[0].addItem();">+</a></div> <div class="section"> <div class="list_equipment listColumns_3"> <div class="template"> <div class="has_tooltip"> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf dsf_equipment_name_ typef"></span><br /> <span class="readonly area dsf dsf_equipment_tootip_ is_tooltip button_float"></span> </div> </div> </div> </div> <div class="section_head">ATTACKS<a class="listAdd interface" title="Add Attack" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_attacks')[0].addItem();">+</a></div> <div class="section" style="position:relative;"> <span class="typea" style="text-decoration:underline;margin-right:30px;">Weapon</span> <span class="typed" style="text-decoration:underline;">Speed</span> <span class="typed" style="text-decoration:underline;">Accuracy</span> <span class="typed" style="text-decoration:underline;">Damage</span> <span class="typed" style="text-decoration:underline;">Defense</span> <span class="typed" style="text-decoration:underline;">Rate</span> <span class="typed" style="text-decoration:underline;">Range</span> <span class="typed" style="text-decoration:underline;">Tags</span> <div class="list_attacks listColumns_1"> <div class="template"> <div style="position:relative;"> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="dsf typea dsf_attack_weapon_"></span> <span class="dsf typed dsf_attack_speed_" style="position:absolute;left:175px;top:0px;"></span> <span class="dsf typed dsf_attack_accuracy_" style="position:absolute;left:251px;top:0px;"></span> <span class="dsf typed dsf_attack_damage_" style="position:absolute;left:327px;top:0px;"></span> <span class="dsf typed dsf_attack_defense_" style="position:absolute;left:403px;top:0px;"></span> <span class="dsf typed dsf_attack_rate_" style="position:absolute;left:479px;top:0px;"></span> <span class="dsf typed dsf_attack_range_" style="position:absolute;left:555px;top:0px;"></span> <span class="dsf typed dsf_attack_tags_" style="position:absolute;left:631px;top:0px;"></span> <br /> </div> </div> </div> </div> <div class="page_foot"> <div class="section_head"> </div> Character By <span class="align_right dsf dsf_player"></span> • Sheet By <span class="align_left dsf dsf_dst_author"></span> </div> </div> <div class="main page_bio" style="display:none;"> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-left.png" class="corner_top_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-right.png" class="corner_top_right" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-left.png" class="corner_bottom_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-right.png" class="corner_bottom_right" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-bottom.png" class="brass_bottom" /> <div class="page_head"> <div class="section_head"> <span class="name dsf dsf_name"></span> </div> <span class="align_right dsf dsf_type typev"></span> • <span class="align_left dsf dsf_campaign"></span> </div> <div class="section_head">BIOGRAPHY</div> <div class="section section_bio"> <span class="portrait_holder"> <span class="portrait dsf dsf_avatar_image"></span> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-left.png" class="portrait_corner_top_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-top-right.png" class="portrait_corner_top_right" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-left.png" class="portrait_corner_bottom_left" /> <img alt="" src="https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-corner-bottom-right.png" class="portrait_corner_bottom_right" /> </span> <span class="dsf dsf_bio"></span> </div> <div class="section_head">APPEARANCE</div> <div class="section"> <span class="area motivation readonly dsf dsf_desc"></span> </div> <div class="section_head">VIRTUE FLAW</div> <div class="section"> <span class="area motivation dsf readonly dsf_virtue_flaw"></span> </div> <div class="section_head">MOTIVATION</div> <div class="section"> <span class="area motivation dsf readonly dsf_motivation"></span> </div> <div class="section_head">INTIMACIES<a class="listAdd interface" title="Add Intimacy" onclick="chainsawxiv_exalted_terrestrial_getElementsByClassName('list_intimacies')[0].addItem();">+</a></div> <div class="section"> <div class="listColumns_1 list_intimacies"> <div class="template"> <div> <a class="listDelete interface" title="Delete this item">✘</a> <a class="listPromote interface" title="Move this item up">↑</a> <a class="listDemote interface" title="Move this item down">↓</a> <span class="typew dsf dsf_intimacy_"></span><br /> </div> </div> </div> </div> <div class="page_foot"> <div class="section_head"> </div> Character By <span class="align_right dsf dsf_player"></span> • Sheet By <span class="align_left dsf dsf_dst_author"></span> </div> </div> </div>
CSS
/* Jedi Input Styles */ div.ds_chainsawxiv_exalted_terrestrial form{ position:relative; } div.ds_chainsawxiv_exalted_terrestrial input { padding:0px 0px 0px 0px; margin:-1px 0px 0px -1px; font-family:palatino; font-size:8pt; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .jeditable_submit{ position:absolute; right:-2px; top:-1px; height:18px; width:10px; } div.ds_chainsawxiv_exalted_terrestrial .jeditable_submit_text { position:relative; top:-4px; left:-1px; font-size:9pt; color:#070; } div.ds_chainsawxiv_exalted_terrestrial .type3{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:150px; } div.ds_chainsawxiv_exalted_terrestrial .type5{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:120px; } div.ds_chainsawxiv_exalted_terrestrial .type7{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:67px; } div.ds_chainsawxiv_exalted_terrestrial .typef{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:193px; } div.ds_chainsawxiv_exalted_terrestrial .typeq{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:576px; } div.ds_chainsawxiv_exalted_terrestrial .typew{ display:inline-block; margin:0px 0px 1px 0px; min-height:16px; width:673px; } div.ds_chainsawxiv_exalted_terrestrial .typer{ display:inline-block; margin:0px 0px 1px 0px; height:16px; float:right; width:123px; text-align:right; } div.ds_chainsawxiv_exalted_terrestrial .typed{ display:inline-block; margin:0px 0px 1px 5px; height:16px; width:68px; text-align:center; } div.ds_chainsawxiv_exalted_terrestrial .typea{ display:inline-block; margin:0px 0px 1px 0px; height:16px; width:142px; text-align:left; } div.ds_chainsawxiv_exalted_terrestrial .typev{ display:inline-block; margin:0px 0px 1px 0px; height:16px; } div.ds_chainsawxiv_exalted_terrestrial span.typev button{ right:1px; } div.editable .dsf{ cursor:pointer; } div.editable .dsf:hover{ color:#4A4844; } div.editable .dsf_bio:hover{ color:#4A4844; cursor:text; } /* Pips Interface Styles */ div.ds_chainsawxiv_exalted_terrestrial .pipsRange_3{ position:relative; z-index:2; float:right; top:3px; width:41px; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px; } div.ds_chainsawxiv_exalted_terrestrial .pipsRange_5{ position:relative; z-index:2; float:right; top:3px; width:70px; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px; } div.ds_chainsawxiv_exalted_terrestrial .pipsRange_10{ position:relative; z-index:2; float:right; top:3px; width:142px; padding:0px 0px 0px 0px; margin:0px 0px 0px 0px; } /* Checks Interface Styles */ div.ds_chainsawxiv_exalted_terrestrial .check{ position:relative; top:1px; margin:0px 3px 0px 0px; } /* List Interface Styles */ div.ds_chainsawxiv_exalted_terrestrial .listAdd{ float:right; cursor:pointer; text-decoration:none; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .listAdd:hover{ color:#4A4844; } div.ds_chainsawxiv_exalted_terrestrial .listDelete{ color:#282622; cursor:pointer; letter-spacing:-1px; text-decoration:none; } div.ds_chainsawxiv_exalted_terrestrial .listDelete:hover{ color:#4A4844; } div.ds_chainsawxiv_exalted_terrestrial .listPromote{ cursor:pointer; letter-spacing:-1px; text-decoration:none; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .listPromote:hover{ color:#4A4844; } div.ds_chainsawxiv_exalted_terrestrial .listDemote{ cursor:pointer; text-decoration:none; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .listDemote:hover{ color:#4A4844; } div.ds_chainsawxiv_exalted_terrestrial .template{ display:none; } div.ds_chainsawxiv_exalted_terrestrial .column{ width:227px; display:inline-block; vertical-align:top; } div.ds_chainsawxiv_exalted_terrestrial .half_sheet_column{ width:340px; display:inline-block; vertical-align:top; } div.ds_chainsawxiv_exalted_terrestrial .double_column{ width:454px; display:inline-block; vertical-align:top; } div.ds_chainsawxiv_exalted_terrestrial .column_spacing{ margin-right:10px; } /* Text Area Interface Styles */ div.ds_chainsawxiv_exalted_terrestrial .area{ font-family:palatino; font-size:9pt; color:#282622; margin:0px 0px 0px 0px; padding:1px 0px 1px 1px; position:absolute; } div.ds_chainsawxiv_exalted_terrestrial .area_submit{ position:absolute; height:16px; width:10px; color:#070; top:0px; right:0px; } div.ds_chainsawxiv_exalted_terrestrial .area_submit_text { position:relative; top:-5px; left:-1px; font-size:9pt; } div.editable .area:hover{ color:#4A4844; } /* Tooltip Interface Styles */ div.ds_chainsawxiv_exalted_terrestrial .has_tooltip{ position:relative; } div.ds_chainsawxiv_exalted_terrestrial .is_tooltip{ display:none; position:absolute; width:180px; min-height:50px; background-color:#ccb894; border-style:solid; border-width:1px; border-color:#282622; padding:2px 4px 2px 6px; z-index:5; left:0px; top:0px; } div.ds_chainsawxiv_exalted_terrestrial .tip_area{ position:relative; left:-4px; } /* Exalted Sheet Styles */ div.ds_chainsawxiv_exalted_terrestrial .wrapper{ position:relative; width:730px; } div.ds_chainsawxiv_exalted_terrestrial .main{ position:relative; width:708px; padding:0px 10px 80px 10px; margin:40px 0px 20px 0px; background-image:url('https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/background.jpg'); background-position:top left; background-repeat:no-repeat; background-color:#e6cea1; border-style:solid; border-width:1px; border-color:#282622; font-family:palatino; font-size:8pt; font-variant:small-caps; line-height:17px; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .small_font{ font-family:palatino; font-size:6pt; font-variant:small-caps; line-height:17px; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .corner_top_left{ position:absolute; left:-7px; top:-7px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .corner_top_right{ position:absolute; right:-7px; top:-7px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .corner_bottom_left{ position:absolute; left:-7px; bottom:-7px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .corner_bottom_right{ position:absolute; right:-7px; bottom:-7px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .brass_bottom{ position:absolute; left:262px; bottom:-7px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .section{ padding:0px 0px 5px 0px; margin:0px 0px 10px 1px; } div.ds_chainsawxiv_exalted_terrestrial .section_head{ font-size:12pt; font-weight:bold; letter-spacing:3px; border-bottom:solid 1px #282622; margin-bottom:5px; } div.ds_chainsawxiv_exalted_terrestrial .page_head{ text-align:center; width:600px; margin:22px 0px 0px 55px; padding:0px 0px 30px 0px; } div.ds_chainsawxiv_exalted_terrestrial .align_right{ text-align:right; } div.ds_chainsawxiv_exalted_terrestrial .align_left{ text-align:left; } div.ds_chainsawxiv_exalted_terrestrial .motivation{ display:inline-block; width:706px; min-height:35px; position:relative; } div.ds_chainsawxiv_exalted_terrestrial .virtue_flaw{ display:inline-block; width:227px; min-height:35px; position:relative; } div.ds_chainsawxiv_exalted_terrestrial .name{ display:inline-block; font-size:18pt; margin:0px 0px 9px 0px; width: 600px; height:16px; } div.ds_chainsawxiv_exalted_terrestrial a{ text-decoration:none; color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .page_foot{ text-align:center; width:600px; margin:22px 0px 0px 55px; padding:0px 0px 30px 0px; position:absolute; bottom:12px; } div.ds_chainsawxiv_exalted_terrestrial .page_bio{ display:none; } div.ds_chainsawxiv_exalted_terrestrial .tab_bar{ position:absolute; top:-36px; right:-5px; z-index:3; background-image:url('https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-tab-left.png'); background-position:top center; background-repeat:no-repeat; height:39px; width:380px; text-align:center; } div.ds_chainsawxiv_exalted_terrestrial .tab{ display:inline-block; width:155px; padding:8px 0px 0px 0px; font-family:palatino; font-size:12pt; font-variant:small-caps; text-align:center; font-weight:bold; color:#282622; cursor:pointer; } div.ds_chainsawxiv_exalted_terrestrial .portrait_holder{ display:inline-block; position:relative; float:right; padding:0px 0px 0px 0px; margin:3px 3px 5px 10px; border-style:solid; border-width:1px; border-color:#282622; } div.ds_chainsawxiv_exalted_terrestrial .portrait_corner_top_left{ position:absolute; left:-4px; top:-4px; width:64px; height:64px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .portrait_corner_top_right{ position:absolute; right:-4px; top:-4px; width:64px; height:64px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .portrait_corner_bottom_left{ position:absolute; left:-4px; bottom:-4px; width:64px; height:64px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .portrait_corner_bottom_right{ position:absolute; right:-4px; bottom:-4px; width:64px; height:64px; z-index:4; } div.ds_chainsawxiv_exalted_terrestrial .section_bio{ margin-bottom:0px; min-height:200px; } div.section a{ text-decoration:underline; }
Javascript
// Global Storage chainsawxiv_exalted_terrestrial_context = {}; /////////////////////////////////////////////////// // Event Hooks //////////////////////////////////// /////////////////////////////////////////////////// // Called immediately before the script fills the Span fields with data function chainsawxiv_exalted_terrestrial_dataPreLoad(opts){ // Set the jeditable button aisleten.characters.jeditableSubmit = '<button class="jeditable_submit"><div class="jeditable_submit_text">✓</div></button>'; aisleten.characters.jeditablePlaceholder = 'Click to edit'; } // Called immediately after the script fills the Span fields with data, before jeditable attachement function chainsawxiv_exalted_terrestrial_dataPostLoad(opts){ // Store global context for search by class name chainsawxiv_exalted_terrestrial_context = document.getElementById(opts['containerId']); // Set additional options opts['imagePath'] = 'https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/'; opts['context'] = document.getElementById(opts['containerId']); opts['debugThreshold'] = -1; //Convert interface elements chainsawxiv_exalted_terrestrial_convertLists(opts); chainsawxiv_exalted_terrestrial_convertPips(opts); chainsawxiv_exalted_terrestrial_convertChecks(opts); chainsawxiv_exalted_terrestrial_convertAreas(opts); chainsawxiv_exalted_terrestrial_convertTips(opts); } // Called immediately before the sheet's data is saved function chainsawxiv_exalted_terrestrial_dataPreSave(opts){ // Set additional options opts['context'] = document.getElementById(opts['containerId']); chainsawxiv_exalted_terrestrial_unconvertPips(opts); chainsawxiv_exalted_terrestrial_unconvertChecks(opts); chainsawxiv_exalted_terrestrial_unconvertAreas(opts); } // Called after any jEditable field changes value function chainsawxiv_exalted_terrestrial_dataChange(opts){ // Identify a data change within a tooltip area and unlock the tooltip oParent = chainsawxiv_exalted_terrestrial_getElementsByClassName("dsf_" + opts['fieldName'],'span')[0].parentNode; if (oParent.className.match('has_tooltip')){ oParent.setAttribute("editLock","unlocked"); oParent.mouseOut(); } } /////////////////////////////////////////////////// // Pips Interface Control ///////////////////////// /////////////////////////////////////////////////// // Applies a bunch of pips functionality to the specified element function chainsawxiv_exalted_terrestrial_pips(oElement,opts){ // Store options oElement.setAttribute('optsImagePath',opts['imagePath']); oElement.setAttribute('optsIsEditable',opts['isEditable']); oElement.setAttribute('optsDebugThreshold',opts['debugThreshold']); // Gets the range of the element from its class name oElement.range = function(){ // Get the range from the element's class name var iRange = this.className.match(/pipsRange_[\d]+/)[0].substring(10); // Default if needed, and return if (iRange != 3 && iRange != 5 && iRange != 7 && iRange != 10){ this.error(1,"Invalid range specification in Pips Element (Element Class: " + this.className + ")"); return 10; } else return iRange; }; // Gets the field value from the embedded image or the text oElement.value = function(){ // Get the value from the image if there is one if (this.getElementsByTagName('img').length){ var sPath = this.getElementsByTagName('img')[0].src; var iValue = parseInt(sPath.substring(sPath.length - 9,sPath.length - 7),10); } // If there's no image, get the value from the text else{ var iValue = parseInt(this.innerHTML); if (this.innerHTML == '') iValue = 0; } // Check the value for bad data, default if needed, and return if (isNaN(iValue) || iValue > this.range() || iValue < 0){ this.error(1,"Invalid value for Pips Element (Element Class: " + this.className + ")"); return 0; } else return iValue; }; // Converts the associated span element's contents to a pips image oElement.showPips = function(){ // Get the image path from options or default if (this.getAttribute('optsImagePath')) var sPath = this.getAttribute('optsImagePath'); else{ this.error(2,'No imagePath specified in options for pips element (Element Class: ' + this.className + ')'); sPath = 'https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/'; } // Skip fields with a value of -1 if (this.value() == -1) return; // Replace the contents with the appropriate pips image this.innerHTML = '<img src="' + sPath + 'pips-' + this.padDigits(this.value(),2) + '-' + this.padDigits(this.range(),2) + '.png" />'; // Activate the pips this.activate(); }; // Converts the associated span element's contents to a text value oElement.showValue = function(){ // Replace the contents with the appropriate value string this.innerHTML = this.value(); }; // Assigns clickability to a pips image element oElement.activate = function(){ // Don't actualy activate anything if we're not in edit mode if (this.getAttribute('optsIsEditable') != 'true') return; // Activate the element's pips interface this.onclick = this.click; // Set the element's alt text this.title = 'Click to set value'; // Set the cursor for the item this.style.cursor = 'pointer'; }; // Click event handler for the pips interface oElement.click = function(e){ // Provide cross-browser support for the event information var oEvent; if (window.event) oEvent = window.event; else oEvent = e; // Set the pixel thresholds for each pip var totalPips = this.padDigits(this.range(),2); var aThresholds; aThresholds = [0,15,30,45,60,78,94,108,123,138]; // Get the pips image that was clicked as a pips object var oImage = this.getElementsByTagName('img')[0]; // Walk up the offset parent tree to get the true click coords var oTemp = oImage; var iX = oTemp.offsetLeft; if (oTemp.offsetParent){ while (oTemp = oTemp.offsetParent){ iX += oTemp.offsetLeft; } } // Determine which pip the click was on and change the image var iClickX = oEvent.clientX - iX; for (var iScore = this.range(); iScore >= 0; iScore--){ if (iClickX > aThresholds[iScore]){ // If the user clicks the current score, they probably want to reduce by one if ((iScore + 1) == this.value()){ oImage.src = oImage.src.substring(0,oImage.src.length - 9) + this.padDigits(iScore,2) + "-" + this.padDigits(this.range(),2) + ".png"; } else{ oImage.src = oImage.src.substring(0,oImage.src.length - 9) + this.padDigits(iScore + 1,2) + "-" + this.padDigits(this.range(),2) + ".png"; } // Once the image has been set, we're done return; // Call the onUpdate event this.onUpdate(); } } }; // Error handling function - alerts on errors if bug reporting is on oElement.error = function(iImportance,sText){ if (this.getAttribute('optsDebugThreshold')) var iThreshold = this.getAttribute('optsDebugThreshold'); else iThreshold = 0; if (iImportance < iThreshold){ alert(sText); } } // Converts a number to a string with prepended zeros to the specified character length oElement.padDigits = function(iNumber,iDigits){ var sNumber = iNumber.toString(); var sTemp = ''; if (iDigits > sNumber.length){ for (var i = 0; i < (iDigits - sNumber.length); i++){ sTemp += '0'; } } return sTemp + sNumber; } // On Update event function, typicaly overriden oElement.onUpdate = function(){ } // Return the pips element for ease of refference return oElement; } // Converts all properly classed spans in the context to pips elements function chainsawxiv_exalted_terrestrial_convertPips(opts){ // Get all the spans in the context, whatever it may be if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); // Convert all the potential values in the context to pips var pTemp = {}; for (var i = 0; i < aSpans.length; i++){ if (aSpans[i].className.match(/pips/)){ pTemp = chainsawxiv_exalted_terrestrial_pips(aSpans[i],opts); pTemp.showPips(); } } } // Converts all the pips in the context back to thier basic values for saving function chainsawxiv_exalted_terrestrial_unconvertPips(opts) { // Get the working context if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); // Flip all the pips in the context back to values for(var i = 0; i < aSpans.length; i++){ if(aSpans[i].className.match(/pips/)){ aSpans[i].showValue(); } } } /////////////////////////////////////////////////// // List Interface Control ///////////////////////// /////////////////////////////////////////////////// // Applies a bunch of list functionality to the specified element function chainsawxiv_exalted_terrestrial_list(oElement,opts){ // Store options oElement.setAttribute('optsContainerId',opts['containerId']); oElement.setAttribute('optsIsEditable',opts['isEditable']); oElement.setAttribute('optsDebugThreshold',opts['debugThreshold']); // Parses the number of columns the list has from its class name oElement.columns = function(){ // Get the column count from the element's class name var iColumns = this.className.match(/listColumns_[\d]+/)[0].substring(12); // Default if needed, and return if (isNaN(iColumns) || iColumns < 1){ this.error(1,"Invalid column count specification in List Element (Element Class: " + this.className + ")"); return 1; } else return iColumns; }; // Gets the list's list item template from the element based on class oElement.template = function(){ // The template is the first div in the list with the "template" class var aDivs = this.getElementsByTagName('div'); for (var i = 0; i < aDivs.length; i++){ if (aDivs[i].className.match(/template/)) return aDivs[i]; } // Create a semi-persistant default row template if needed if (!this.defaultTemplate){ this.defaultTemplate = document.createElement('div'); this.defaultTemplate.innerHTML = '<span class="dsf"></span>'; } // If we got here, there wasn't a template in the list, default and return this.error(1,"No template row found in List Element (Element Class: " + this.className + ")"); return this.defaultTemplate; }; // Gets an array of the fields in the template row oElement.fields = function(){ // This is easy assuming all the fields are span tags, and all the spans are fields return this.template().getElementsByTagName('span'); } // Gets an array of the rows in the list, excluding the template oElement.rows = function(){ // Initialize the list of rows var aRows = new Array(); // Getting the divs in the list the hard way to avoid nested divs making the cut var aElements = this.childNodes; var aDivs = new Array(); var iCounter = 0; for (var n = 0; n < aElements.length; n++){ if (aElements[n].tagName == 'DIV'){ aDivs[iCounter] = aElements[n]; iCounter++; } } // If we have multiple columns, then get the rows from inside each one if (this.columns() > 1){ var aTemp = new Array(); for (var x = 0; x < aDivs.length; x++){ if (!aDivs[x].className.match(/template/)){ aTemp = aDivs[x].getElementsByTagName('div'); for (var y = 0; y < aTemp.length; y++){ aRows[aRows.length] = aTemp[y]; } } } } // Otherwise just get them all from the main div else{ for (var i = 1; i < aDivs.length; i++){ aRows[aRows.length] = aDivs[i]; } } // Return the array of rows // This may have been dissacoiated by the splices, not sure yet return aRows; } // Generates a structure containing the list's data from the save object oElement.loadData = function(){ // Pattern match on the first field for simplicity's sake var iCounter = 0; var oData = {}; // Get the fields in order (doesn't allow missing fileds) var sClassPattern = this.fields()[0].className.match(/dsf_[\w\d]+/)[0].substring(4); while (dynamic_sheet_attrs[sClassPattern + this.padDigits(iCounter,2)] != undefined){ oData[iCounter] = new Array(); for (var i = 0; i < this.fields().length; i++){ oData[iCounter][i] = dynamic_sheet_attrs[this.fields()[i].className.match(/dsf_[\w\d]+/)[0].substring(4) + this.padDigits(iCounter,2)]; } iCounter++; } // Write the length oData.length = iCounter; // Write the completed data structure to the object this.data = oData; } // Generates a structure contianing the list's data form the list itself oElement.parseData = function(){ // Go through each row of each field and populate the structure var oData = {}; oData.length = 0; for (var i = 0; i < this.rows().length; i++){ oData[i] = new Array(); for (var n = 0; n < this.fields().length; n++){ oData[i][n] = this.rows()[i].getElementsByTagName('span')[n].innerHTML } oData.length = i + 1; } // Write the completed data structure to the object this.data = oData; } // Renders out the code for the list and puts it into the list element oElement.render = function(){ var sTemp = ''; var iCurrentColumn = 1; var iBreak = 0; var sClass = ''; // Add the first column opener if multiple columns, and calc first col break if (this.columns() > 1){ sTemp = '\n<div class="column column_spacing">'; iBreak += Math.floor(this.data.length / this.columns()) - 1; if (iCurrentColumn <= (this.data.length % this.columns())) iBreak++; } // Accumulate the list code for each row for (var i = 0; i < this.data.length; i++){ // Populate and class the fields for (var n = 0; n < this.fields().length; n++){ this.fields()[n].className = this.fields()[n].className.replace(/dsf_[\w\d]+/,this.fields()[n].className.match(/dsf_[\w\d]+/)[0] + this.padDigits(i,2)); this.fields()[n].innerHTML = this.data[i][n]; } // Add the list item to the code sTemp += this.template().innerHTML; // Reset the template if it was used for (var x = 0; x < this.fields().length; x++){ sClass = this.fields()[x].className.match(/dsf_[\w\d]+/)[0]; this.fields()[x].className = this.fields()[x].className.replace(/dsf_[\w\d]+/,sClass.substring(0,sClass.length - 2)); this.fields()[x].innerHTML = ''; } // Add column breaks where needed if (this.columns() > 1 && (i == iBreak)){ // Add the column opener for the last column if (iCurrentColumn == (this.columns() - 1)) sTemp += '</div>\n<div class="column">'; // Add the final column's column closer else if (i == (this.data.length - 1)) sTemp += '</div>'; // Add the column openers for other columns else sTemp += '</div>\n<div class="column column_spacing">'; // Update the column break and current column iCurrentColumn++; iBreak += Math.floor(this.data.length / this.columns()); if (iCurrentColumn <= (this.data.length % this.columns())) iBreak++; } } // Prepend the template to the list code sTemp = '<div class="template">' + this.template().innerHTML + '</div>' + sTemp; // Purge jquery expandos in explorer sTemp = sTemp.replace(/jQuery[\d]+="[\d]+"/g,''); // Put the code in the list this.innerHTML = sTemp; // Activate the interface if in edit mode if (this.getAttribute('optsIsEditable') == 'true'){ // Look through all the anchor elements in the list and activate by class name var aButtons = this.getElementsByTagName('a'); for (var y = 0; y < aButtons.length;y++){ if(aButtons[y].className.match(/listDelete/)) aButtons[y].onclick = this.deleteItem; else if(aButtons[y].className.match(/listPromote/)) aButtons[y].onclick = this.promoteItem; else if(aButtons[y].className.match(/listDemote/)) aButtons[y].onclick = this.demoteItem; } } // Hide them if not else{ // Look through all the anchor elements in the list and hide by class name var oContext = document.getElementById(this.getAttribute('optsContainerId')); if (oContext) var aButtons = oContext.getElementsByTagName('a'); else{ this.error(2,'No context specified in options for list element (Element Class: ' + this.className + ')'); var aButtons = document.getElementsByTagName('a'); } for (var y = 0; y < aButtons.length; y++){ if(aButtons[y].className.match(/interface/)) aButtons[y].style.display = 'none'; } } // Triger the list's onUpdate event this.onUpdate(); }; // Adds an blank element to the list oElement.addItem = function(){ // Get the latest data from the list this.parseData(); // Add a new row to the data, full of blank values var aRow = new Array(); for (var i = 0; i < this.fields().length; i++){ aRow[i] = ''; } this.data[this.data.length] = aRow; this.data.length++; // Re-render the list this.render(); }; // Deletes the specified element from the list oElement.deleteItem = function(){ // Activate the list the item belongs to var oItem = this.parentNode; if (oItem.parentNode.className.match(/list/)) var lList = oItem.parentNode; else var lList = oItem.parentNode.parentNode; // Stop here if we're editing things if (oItem.innerHTML.match(/input/)) return; // Delete the item from the DOM oItem.parentNode.removeChild(oItem); // Refresh the list to renew numbering lList.parseData(); lList.render(); }; // Moves the specified element up the list one place oElement.promoteItem = function(){ // Activate the list the item belongs to var oItem = this.parentNode; if (oItem.parentNode.className.match(/list/)) var lList = oItem.parentNode; else var lList = oItem.parentNode.parentNode; // Stop here if we're editing things if (oItem.innerHTML.match(/input/)) return; // Get the latest data from the list lList.parseData(); // Figure out what row number was clicked var sFieldClass = oItem.getElementsByTagName('span')[0].className.match(/dsf_[\w\d]+/)[0]; var sIndexString = sFieldClass.substring(sFieldClass.length - 2).replace(/^[0]+/,''); var iIndex = parseInt(sIndexString); // Stop right here if the clicked item is already at the top if (iIndex == 0) return; // Swap the row data with the one above it var aRowA = lList.data[iIndex]; var aRowB = lList.data[iIndex - 1]; lList.data[iIndex] = aRowB; lList.data[iIndex - 1] = aRowA; // Re-render the data lList.render(); }; // Moves the specified element down the list one place oElement.demoteItem = function(){ // Activate the list the item belongs to var oItem = this.parentNode; if (oItem.parentNode.className.match(/list/)) var lList = oItem.parentNode; else var lList = oItem.parentNode.parentNode; // Stop here if we're editing things if (oItem.innerHTML.match(/input/)) return; // Get the latest data from the list lList.parseData(); // Figure out what row number was clicked var sFieldClass = oItem.getElementsByTagName('span')[0].className.match(/dsf_[\w\d]+/)[0]; var sIndexString = sFieldClass.substring(sFieldClass.length - 2).replace(/^[0]+/,''); var iIndex = parseInt(sIndexString); // Stop right here if the clicked item is alreayd on the bottom if (iIndex == (lList.data.length - 1)) return; // Swap the row data with the one below it var aRowA = lList.data[iIndex]; var aRowB = lList.data[iIndex + 1]; lList.data[iIndex] = aRowB; lList.data[iIndex + 1] = aRowA; // Re-render the data lList.render(); }; // Error handling function - alerts on errors if bug reporting is on oElement.error = function(iImportance,sText){ if (this.getAttribute('optsDebugThreshold')) var iThreshold = this.getAttribute('optsDebugThreshold'); else iThreshold = 0; if (iImportance < iThreshold){ alert(sText); } } // Converts a number to a string with prepended zeros to the specified character length oElement.padDigits = function(iNumber,iDigits){ var sNumber = iNumber.toString(); var sTemp = ''; if (iDigits > sNumber.length){ for (var i = 0; i < (iDigits - sNumber.length); i++){ sTemp += '0'; } } return sTemp + sNumber; } // On Update event function, typicaly overriden oElement.onUpdate = function(){ } // Return the origenal element now that it's fully equipped return oElement; } // Converts all properly classed divs in the context to lists function chainsawxiv_exalted_terrestrial_convertLists(opts){ // Find all the divs on the page with "list" in their class name if (opts['context']) var aDivs = opts['context'].getElementsByTagName('div'); else var aDivs = document.getElementsByTagName('div'); var lTemp = {}; for (var i = 0; i < aDivs.length; i++){ if (aDivs[i].className.match(/list/)){ // Convert each element to a full featured list object lTemp = chainsawxiv_exalted_terrestrial_list(aDivs[i],opts); // Populate the list from the data variable lTemp.loadData(); lTemp.render(); // Assign the onUpdate function lTemp.onUpdate = function(){ chainsawxiv_exalted_terrestrial_convertPips(opts); chainsawxiv_exalted_terrestrial_convertChecks(opts); chainsawxiv_exalted_terrestrial_convertTips(opts); chainsawxiv_exalted_terrestrial_convertAreas(opts); aisleten.characters.bindAllFields(opts['slug'],opts['containerId']); //dst_devkit.bindDynamicAttributes(); } } } } /////////////////////////////////////////////////// // Text Area Edit Control ///////////////////////// /////////////////////////////////////////////////// // Core Textarea Class function chainsawxiv_exalted_terrestrial_area(oElement,opts){ // Store options oElement.setAttribute('optsIsEditable',opts['isEditable']); oElement.setAttribute('optsDebugThreshold',opts['debugThreshold']); // Attaches edit events to area text oElement.activate = function(){ // Don't activate the element if we're not in edit mode if (this.getAttribute('optsIsEditable') != 'true') return; // Activate the element oElement.onclick = this.edit; // Add default value if (this.innerHTML == '') this.innerHTML = 'Click to edit'; // Set the element's alt text this.title = 'Click to edit'; // Set the cursor for the item this.style.cursor = 'pointer'; }; // Converts the element to an editable area oElement.edit = function(){ // Abort click function if we just clicked submit if(this.getAttribute('eventLock') == 'locked'){ this.setAttribute('eventLock',null); return; } // Force submit any other area in the context var aAreas = chainsawxiv_exalted_terrestrial_getElementsByClassName('area','span'); for (var i = 0; i < aAreas.length; i++){ if (aAreas[i].getAttribute('status') == 'editing') aAreas[i].submit(); } // Set the editing flag this.setAttribute('status','editing'); // Disable click functionality this.onclick = null; // Set cursor this.style.cursor = 'text'; // Remove default if (this.innerHTML == 'Click to edit') this.innerHTML = ''; // Convert <br /> tags to line breaks var sText = this.innerHTML.replace(/<br>/g,'\n'); // Select dimensions and classes var iWidth = this.offsetWidth + parseInt(this.getAttribute('widthMod')); var iHeight = this.offsetHeight + parseInt(this.getAttribute('heightMod')); var sClasses = this.getAttribute('areaClasses'); // Convert content into form with button this.innerHTML = '<textarea class="' + sClasses + '" style="width:' + iWidth + 'px;height:' + iHeight + 'px;">' + sText + '</textarea>'; this.innerHTML += '<button class="submit_button area_submit" onClick="this.parentNode.submit();"><div class="area_submit_text">✓</div></button>'; // Set the user's focus to the textarea var focusRef = function(){oElement.getElementsByTagName('textarea')[0].focus();}; this.focusTimeout = setTimeout(focusRef,50); }; // Converts the edit box back into regular text form oElement.submit = function(){ // Get the data from the edit box var sContent = this.getElementsByTagName('textarea')[0].value.replace(/\n/g,'<br>'); // Remove the form elements this.innerHTML = sContent; // Reapply the default value if needed if (this.innerHTML == '') this.innerHTML = 'Click to edit'; // Lock out the click event until we're done this.setAttribute('eventLock','locked'); // Automatically unlock after a twentieth of a second var submitRef = function(){oElement.setAttribute('eventLock',null);}; this.timeout = setTimeout(submitRef,50); // Set pointer this.style.cursor = 'pointer'; // Reattach the click functionality this.onclick = this.edit; // Reset the editing flag this.setAttribute('status',null); // Call the onUpdate event this.onUpdate(); }; // On Update event function, typicaly overriden oElement.onUpdate = function(){ } // Error handling function - alerts on errors if bug reporting is on oElement.error = function(iImportance,sText){ if (this.getAttribute('optsDebugThreshold')) var iThreshold = this.getAttribute('debugThreshold'); else iThreshold = 0; if (iImportance < iThreshold){ alert(sText); } } // Return the element for ease of refference return oElement; } // Converts all properly classed divs in the context to lists function chainsawxiv_exalted_terrestrial_convertAreas(opts){ // Find all the spans on the page with "area" in their class name if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); var taTemp = {}; for (var i = 0; i < aSpans.length; i++){ if (aSpans[i].className.match(/area/)){ // Convert each element to a full featured list object taTemp = chainsawxiv_exalted_terrestrial_area(aSpans[i],opts); taTemp.activate(); // Load up custom parameters and such depending on class if (aSpans[i].className.match('is_tooltip')){ taTemp.setAttribute('widthMod',-9); taTemp.setAttribute('heightMod',-9); taTemp.setAttribute('areaClasses','area tip_area'); taTemp.onUpdate = function(){ oParent = this.parentNode; oParent.setAttribute("editLock","unlocked"); oParent.mouseOut(); }; } else{ taTemp.setAttribute('widthMod',-23); taTemp.setAttribute('heightMod',-6); taTemp.setAttribute('areaClasses','area'); } } } } // Sets the necesary class name on areas for themt o be saved function chainsawxiv_exalted_terrestrial_unconvertAreas(opts){ // Find all the spans on the page with "area" in their class name if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); // Add the necesary save key to the class name // Also close out any active edit boxes for (var i = 0; i < aSpans.length; i++){ if (aSpans[i].className.match(/area/)){ if (aSpans[i].innerHTML.match(/textarea/)) aSpans[i].submit(); if (aSpans[i].innerHTML == 'Click to edit') aSpans[i].innerHTML = ''; } } } /////////////////////////////////////////////////// // Check Interface Control //////////////////////// /////////////////////////////////////////////////// // Applies a bunch of pips functionality to the specified element function chainsawxiv_exalted_terrestrial_check(oElement,opts){ // Store options oElement.setAttribute('optsImagePath',opts['imagePath']); oElement.setAttribute('optsIsEditable',opts['isEditable']); oElement.setAttribute('optsDebugThreshold',opts['debugThreshold']); // Parses the title from the class name oElement.getTitle = function(){ // Get the column count from the element's class name var sTitle = this.className.match(/title_[\w\d\s]+/); if (sTitle) sTitle = sTitle[0].substring(6); return sTitle; }; // Gets the field value from the embedded image or the text oElement.value = function(){ // Get the value from the image if there is one if (this.getElementsByTagName('img').length){ var sPath = this.getElementsByTagName('img')[0].src; var sValue = sPath.substring(sPath.length - 5,sPath.length - 4); } // If there's no image, get the value from the text else{ var sValue = this.innerHTML; if (this.innerHTML == '') sValue = '0'; } // Check the value for bad data, default if needed, and return if (sValue != '1' && sValue != '0'){ this.error(1,"Invalid value for Check Element (Element Class: " + this.className + ")"); return 0; } else return sValue; }; // Converts the associated span element's contents to a pips image oElement.showCheck = function(){ // Get the image path from options or default if (this.getAttribute('optsImagePath')) var sPath = this.getAttribute('optsImagePath'); else{ this.error(2,'No imagePath specified in options for Checks element (Element Class: ' + this.className + ')'); sPath = 'https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/'; } // Replace the contents with the appropriate check image this.innerHTML = '<img src="' + sPath + 'check-' + this.value() + '.png" />'; // Activate the check this.activate(); }; // Converts the associated span element's contents to a text value oElement.showValue = function(){ // Replace the contents with the appropriate value string this.innerHTML = this.value(); }; // Assigns clickability to a pips image element oElement.activate = function(){ // Don't actualy activate anything if we're not in edit mode if (this.getAttribute('optsIsEditable') != 'true') return; // Activate the element's pips interface this.onclick = this.click; // Set the element's alt text this.title = this.getTitle(); if (!this.title) this.title = 'Click to set value'; // Set the cursor for the item this.style.cursor = 'pointer'; }; // Click event handler for the pips interface oElement.click = function(){ // Get the pips image that was clicked as a pips object var oImage = this.getElementsByTagName('img')[0]; // Determine which pip the click was on and change the image if (this.value() == "1") oImage.src = oImage.src.substring(0,oImage.src.length - 5) + "0.png"; else oImage.src = oImage.src.substring(0,oImage.src.length - 5) + "1.png"; // Call the onUpdate event this.onUpdate(); }; // Error handling function - alerts on errors if bug reporting is on oElement.error = function(iImportance,sText){ if (this.getAttribute('optsDebugThreshold')) var iThreshold = this.getAttribute('optsDebugThreshold'); else iThreshold = 0; if (iImportance < iThreshold){ alert(sText); } } // On Update event function, typicaly overriden oElement.onUpdate = function(){ } // Return the pips element for ease of refference return oElement; } // Converts all properly classed spans in the context to pips elements function chainsawxiv_exalted_terrestrial_convertChecks(opts){ // Get all the spans in the context, whatever it may be if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); // Convert all the potential values in the context to pips var pTemp = {}; for (var i = 0; i < aSpans.length; i++){ if (aSpans[i].className.match(/check/)){ pTemp = chainsawxiv_exalted_terrestrial_check(aSpans[i],opts); pTemp.showCheck(); } } } // Converts all the pips in the context back to thier basic values for saving function chainsawxiv_exalted_terrestrial_unconvertChecks(opts) { // Get the working context if (opts['context']) var aSpans = opts['context'].getElementsByTagName('span'); else var aSpans = document.getElementsByTagName('span'); // Flip all the pips in the context back to values for(var i = 0; i < aSpans.length; i++){ if(aSpans[i].className.match(/check/)){ aSpans[i].showValue(); } } } /////////////////////////////////////////////////// // Tool Tip Control /////////////////////////////// /////////////////////////////////////////////////// function chainsawxiv_exalted_terrestrial_tip(oElement,opts){ // Store options oElement.setAttribute('optsIsEditable',opts['isEditable']); oElement.setAttribute('optsDebugThreshold',opts['debugThreshold']); // Gets the tip display oElement.tip = function(){ // Search the link's context for the tip element var aSpans = this.getElementsByTagName('span'); for (var i = 0; i < aSpans.length; i++){ if (aSpans[i].className.match('is_tooltip')){ return aSpans[i]; } } return false; }; // Assigns event functionality to a field oElement.activate = function(){ // Register the hover events this.onmouseover = this.showTip; this.onmouseout = this.mouseOut; this.tip().onmouseout = this.mouseOut; // Don't actualy activate anything if we're not in edit mode if (this.getAttribute('optsIsEditable') != 'true') return; // Activate the element's edit event this.onmouseup = this.mouseUp; // Set the cursor for the item this.style.cursor = 'pointer'; }; // Shows the tool tip, event handler for mouseover oElement.showTip = function(){ // If we're not in edit mode and the tip is empty, show nothing if (this.getAttribute('optsIsEditable') != 'true' && (this.tip().innerHTML == '' || this.tip().innerHTML == 'undefined')) return; // Clear the hide timer if we're still over the element if (this.timeout){ clearTimeout(this.timeout); return; } // If we're editing the field, abort if (this.getAttribute("editLock") == "locked") return; // Capture the tool tip element var oTip = this.tip(); // Position the tooltip under the main element oTip.style.top = this.offsetHeight + 'px'; // Show the tool tip oTip.style.display = 'block'; }; // Hides the tool tip, event handler for mouseout oElement.hideTip = function(){ // Abort the hide if we're editing if (this.getAttribute("editLock") == "locked") return; // Hide the tool tip this.tip().style.display = 'none'; // Reset the hide timer this.timeout = false; }; // Handles the mouseout event for the tooltip oElement.mouseOut = function(){ // Abort the event completely if we're editing if (this.getAttribute("editLock") == "locked") return; // Delays the hide by a 20th of a second // This allows mouseover to cancel hide for sub elements var hideRef = function(){chainsawxiv_exalted_terrestrial_tip(oElement,opts).hideTip();}; this.timeout = setTimeout(hideRef,50); }; // Click event handler for the tool tip interface oElement.mouseUp = function(e){ // Cross browser event data getter var sClickedClass = ''; if (!e) sClickedClass = window.event.srcElement.className; else sClickedClass = e.target.className; // Abort out if a non-jEditable thing was clicked if (!sClickedClass.match('dsf') || (sClickedClass.match('readonly') && !sClickedClass.match('area'))) return; // Hide the tooltip if that's not what we're editing if (!sClickedClass.match('is_tooltip')) this.hideTip(); // If we're not already editing, lock the tooltip if (this.getAttribute("editLock") != "locked") this.setAttribute("editLock","locked"); }; // Error handling function - alerts on errors if bug reporting is on oElement.error = function(iImportance,sText){ if (this.getAttribute('optsDebugThreshold')) var iThreshold = this.getAttribute('optsDebugThreshold'); else iThreshold = 0; if (iImportance < iThreshold){ alert(sText); } } // Return the pips element for ease of refference return oElement; } // Converts all properly classed divs in the context to pips elements function chainsawxiv_exalted_terrestrial_convertTips(opts){ // Get all the divs in the context, whatever it may be if (opts['context']) var aDivs = opts['context'].getElementsByTagName('div'); else var aDivs = document.getElementsByTagName('div'); // Convert all the potential values in the context to pips var pTemp = {}; for (var i = 0; i < aDivs.length; i++){ if (aDivs[i].className.match(/has_tooltip/)){ pTemp = chainsawxiv_exalted_terrestrial_tip(aDivs[i],opts); pTemp.activate(); } } } /////////////////////////////////////////////////// // General Utility Functions ////////////////////// /////////////////////////////////////////////////// // Gets an array of elements with a particular class from the context function chainsawxiv_exalted_terrestrial_getElementsByClassName(sClassName,sElementType){ // Provide default element type if (!sElementType) sElementType = 'div'; var aList = new Array(); var aDivs = chainsawxiv_exalted_terrestrial_context.getElementsByTagName(sElementType); for (var i = 0; i < aDivs.length; i++){ if (aDivs[i].className.match(sClassName)) aList[aList.length] = aDivs[i]; } return aList; } // Tab switching function function chainsawxiv_exalted_terrestrial_tabClick(oTab,sPageClass){ // Abort if already on the selected tab var oPage = chainsawxiv_exalted_terrestrial_getElementsByClassName('page_' + sPageClass)[0]; if (oPage.style.display != 'none') return; // Set the length of the shorter page to match the longer page var oPages = chainsawxiv_exalted_terrestrial_getElementsByClassName('main'); var iHeight = 0; for (var i = 0; i < oPages.length; i++){ if (oPages[i].offsetHeight > iHeight) iHeight = oPages[i].offsetHeight; } for (var n = 0; n < oPages.length; n++){ oPages[n].style.minHeight = (iHeight - 140) + 'px'; } // Corelate the 'type' fields on the two pages var aTypes = chainsawxiv_exalted_terrestrial_getElementsByClassName('dsf_type','span'); if (sPageClass == 'sheet'){ aTypes[0].innerHTML = aTypes[1].innerHTML; } else{ aTypes[1].innerHTML = aTypes[0].innerHTML; } // Show the proper pages and tabs if (sPageClass == 'sheet'){ oTab.parentNode.style.backgroundImage = "url(https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-tab-left.png)"; chainsawxiv_exalted_terrestrial_getElementsByClassName('page_sheet')[0].style.display = 'block'; chainsawxiv_exalted_terrestrial_getElementsByClassName('page_bio')[0].style.display = 'none'; } else{ oTab.parentNode.style.backgroundImage = "url(https://chainsawxiv.github.io/DST/sheets/chainsawxiv_exalted_terrestrial/images/brass-tab-right.png)"; chainsawxiv_exalted_terrestrial_getElementsByClassName('page_bio')[0].style.display = 'block'; chainsawxiv_exalted_terrestrial_getElementsByClassName('page_sheet')[0].style.display = 'none'; } }
Submit Notes
Back