JavaScript in character sheets

A work-in-progress reference for JavaScript in character sheets, to be turned into a proper guide once I have played more with it.

Exposing attribute values and other info about the entity

As of Kanka 2.3, the variables available in Blade are not directly exposed in JavaScript out of the box. To handle them in your script, you will need to obtain them from the elements rendered on the page. You may only need a few of them, in which case the following code would be overkill, but I have devised an exhaustive dump of all variables provided in Blade into a hidden HTML element that can then be referenced in JavaScript to build a single object:

Blade component
<div id="blade-dump" class="hidden" data-locale="{{$_locale}}" data-name="{{$_entity_name}}" data-type="{{$_entity_type}}" data-etype="{{$_entity_type_name}}" data-tags="@foreach($_tags as $tag){{$tag}} @endforeach" data-title="{{$_character_title}}" data-gender="{{$_character_gender}}" data-pronouns="{{$_character_pronouns}}" data-age="{{$_character_age}}">
    <div id="dump-attributes">
    @foreach($attributes as $name => $value)
        <div data-name="{{$name}}">{!!$value!!}</div>
    @endforeach
    </div>
    <div id="dump-traits">
    @foreach($_character_traits as $name => $value)
        <div data-name="{{$name}}" data-value="{!!$value!!}"></div>
    @endforeach
    </div>
    <div id="dump-appearances">
    @foreach($_character_appearances as $name => $value)
        <div data-name="{{$name}}" data-value="{!!$value!!}"></div>
    @endforeach
    </div>
    <div id="dump-abilities">
    @foreach($_abilities as $ability)
    	@if($ability = $_abilities[$loop -> index]) @endif
        <div id="dump-ability-{{$loop -> index}}" data-name="{{ $ability["name"] }}" data-type="{{ $ability["type"] }}" data-tags="@foreach($ability["tags"] as $tag){{$tag}} @endforeach " @isset($ability["parent"]) data-parent="{{ $ability["parent"]["name"] }}" @endisset @isset($ability["charges"]) data-charges="{{ $ability["charges"] }}" data-charges-used="{{ $ability["used_charges"] ?: 0 }}" @endisset>
            {!! $ability["link"] !!}
            {!! $ability["thumb"] !!}
            <div class="ability-entry">{!! $ability["entry"] !!}</div>
        </div>
    @endforeach
    </div>
</div>
JavaScript component
// Grab each dump
const bdump = document.getElementById("blade-dump").dataset,
	attdump = document.querySelectorAll("#dump-attributes > *"),
	tdump = document.querySelectorAll("#dump-traits > *"),
	appdump = document.querySelectorAll("#dump-appearances > *"),
	abidump = document.querySelectorAll("#dump-abilities > *");
// Initialize objects
var attributes = {}, traits = {}, appearances = {}, abilities = [];
// Populate each object
attdump.forEach((child) => {
	attributes[child.dataset.name] = child.innerHTML.replace(/\n/g, "");
});
tdump.forEach((child) => {
	traits[child.dataset.name] = child.innerHTML.replace(/\n/g, "");
});
appdump.forEach((child) => {
	appearances[child.dataset.name] = child.innerHTML.replace(/\n/g, "");
});
abidump.forEach((child) => {
	abilities.push({"name": child.dataset.name,
		"type": child.dataset.type,
		"tags": child.dataset.tags.trim().split(" "),
		"link": child.querySelector(".ability-link").href,
		"thumb": child.querySelector(".ability-thumb").src,
		"entry": child.querySelector(".ability-entry").innerHTML.replace(/\n/g, "")
	});
});
const sheet = {
	"locale": bdump.locale,
	"name": bdump.name,
	"ctype": bdump.type,
	"etype": bdump.etype,
	"tags": bdump.tags.trim().split(" "),
	"title": bdump.title,
	"gender": bdump.gender,
	"pronouns": bdump.pronouns,
	"age": bdump.age,
	"attributes": attributes,
	"abilities": abilities,
	"traits": traits,
	"appearances": appearances
};

This script comes up to about 1,430 characters out of 60,000 allowed in the JS field. You could shave off a few by condensing it further, but I wanted to keep it legible for this guide, and keep in mind that JS must pass review for your plugin to be approved.

Simple values can then be used directly with the sheet.name syntax, and more complex ones used in loops like:

// Add each ability name to a list as a link
sheet.abilities.forEach((c) => {
    document.querySelector("#ability-list").innerHTML += `<li><a href="${c.link}">${c.name}</a></li>`;
});

Last updated