Provides extensibility APIs for customizing various aspects of Tidy 5e Sheets.
Constants for a variety of uses.
The attribute which indicates a particular part of a sheet.
Values used in conjunction with the attribute api.constants.SHEET_PART_ATTRIBUTE to identify a part of a Tidy 5e sheet.
<div class="actor-name" data-tidy-sheet-part="name-container">...</div>
// Every time Tidy renders, whether a full render or a partial
Hooks.on("tidy5e-sheet.renderActorSheet", (sheet, element, data) => {
const api = game.modules.get('tidy5e-sheet').api;
const selector = api.getSheetPartSelector(
api.constants.SHEET_PARTS.NAME_CONTAINER
);
// get the name container of the target actor sheet
element
.querySelector(selector)
// inject some HTML
?.insertAdjacentHTML(
// put it as the first element inside the name container; see https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML#afterbegin
"afterbegin",
// here's my content
// pro tip: `data-tidy-render-scheme="handlebars"` causes this content to re-render on every Tidy render, full or partial
`<h2 type="button" style="width: 100%;" data-tidy-render-scheme="handlebars"><i class="fa-solid fa-star"></i></h2>`
);
});
Tidy 5e Sheets are tagged with data-tidy-sheet-part attributes
so that most parts of the sheet can be generally identified.
This module uses specific attributes rather than classes because of
HTML classes' multiple purposes, including use for CSS styling.
Using sheet part attributes allows for identifying the same general thing
even when considering a potentially alternate Tidy sheet layout.
ReadonlyABILITY_CONFIGURATION_CONTROL: "ability-configuration-control"An interactable control that can open configuration settings for a target ability.
ReadonlyABILITY_ROLLER: "ability-roller"A rollable/interactable element which rolls an ability save or test.
ReadonlyABILITY_SAVE_PROFICIENCY_TOGGLE: "ability-save-proficiency-toggle"An interactable toggle for ability saving throw proficiency.
ReadonlyABILITY_SAVE_ROLLER: "ability-save-roller"A rollable/interactable element which rolls an ability save.
ReadonlyABILITY_SCORE: "ability-score"An ability score (e.g., "str", "dex", "wis", etc.), whether readonly or editable.
ReadonlyABILITY_SCORE_CONTAINER: "ability-score-container"A container for a given ability score (e.g., "str", "dex", "wis", etc.).
ReadonlyABILITY_TEST_ROLLER: "ability-test-roller"A rollable/interactable element which rolls an ability test.
ReadonlyACTION_BAR: "action-bar"A toolbar with available actions for affeting the contents of a tab, usually item table contents (e.g., filter, sort, config).
ReadonlyACTIVITY_TABLE_ROW: "activity-table-row"A row in an activity table.
ReadonlyACTOR_PORTRAIT_CONTAINER: "actor-portrait-container"A container which houses an actor portrait and other parts related to actor portrait features.
ReadonlyACTOR_PORTRAIT_HEALTH_OVERLAY: "actor-portrait-health-overlay"An overlay element for an actor portrait which provides a visual representation of remaining health.
ReadonlyACTOR_PORTRAIT_IMAGE: "actor-portrait-image"An actor portrait image element.
ReadonlyACTOR_TRAIT: "actor-trait"An actor trait container, such as Senses, Languages, or Tools.
ReadonlyACTOR_TRAIT_DETAILS: "actor-trait-details"The specific details of an actor trait container, such as Senses, Languages, or Tools.
ReadonlyADVANCEMENT_TABLE_ROW: "advancement-table-row"A row in an advancement table.
ReadonlyCONDITION_TOGGLE: "condition-toggle"A control for toggling a condition
ReadonlyDAMAGE_PART_CONTAINER: "damage-part-container"A container for all form fields related to a given damage part.
ReadonlyDAMAGE_PART_DELETE_COMMAND: "damage-part-delete-command"An interactable control which the user can execute to delete a damage part to an item.
ReadonlyDAMAGE_PART_FORMULA: "damage-part-formula"An input element which contains a damage part formula, usually for an item.
ReadonlyDAMAGE_PART_TYPE: "damage-part-type"An input element which represents the damage type of a damage part, usually for an item.
ReadonlyDEATH_SAVE_FAILURES: "death-save-failures"An input for the number of failed death saves an actor has.
ReadonlyDEATH_SAVE_ROLLER: "death-save-roller"A rollable/interactable element which rolls a death saving throw.
ReadonlyDEATH_SAVE_SUCCESSES: "death-save-successes"An input for the number of successful death saves an actor has.
ReadonlyEFFECT_TABLE_ROW: "effect-table-row"A row in an effect table.
ReadonlyEXPANSION_TOGGLE: "table-expansion-toggle"An interactable element which toggles a view
ReadonlyGROUP_MEMBER_PORTRAIT: "group-member-portrait"An image representing a member of a group sheet.
ReadonlyINLINE_CONTAINER_TOGGLE: "inline-container-toggle"An interactable element which toggles an inline container's contents view
ReadonlyITEM_CREATE_COMMAND: "item-create-command"An interactable control which the user can execute to create an item (e.g., consumable, feature, loot, spell, weapon, etc.).
ReadonlyITEM_IMAGE: "item-image"An image element for an item.
ReadonlyITEM_IMAGE_CONTAINER: "item-image-container"The container element for an item image.
ReadonlyITEM_NAME: "item-name"An element which contains the name of an item.
ReadonlyITEM_PROPERTY_LIST: "item-property-list"A series of properties related to an item, to be found on item summaries, item cards, and other locations where read-only item information is given.
ReadonlyITEM_SHEET_PROPERTIES: "item-sheet-properties"A series of properties related to an item, viewed from that item's sheet. These include read-only properties, currency value, and other situational input.
ReadonlyITEM_SUMMARY: "item-summary"A summary of an item, usually taken from the item's chat data.
ReadonlyITEM_TABLE: "item-table"A list-based tabular representation of items (e.g., equipment, loot, spells, etc.).
ReadonlyITEM_TABLE_HEADER_ROW: "item-table-header-row"The header row of an item table.
ReadonlyITEM_TABLE_ROW: "item-table-row"A row in an item table.
ReadonlyITEM_USE_COMMAND: "item-use-command"An interactable control which the user can execute to use an item (e.g., consumable, feature, loot, spell, weapon, etc.).
ReadonlyITEMS_CONTAINER: "items-container"A containing element for a series of item lists or grids.
ReadonlyMELEE_SPELL_ATTACK_MOD: "melee-spell-attack-mod"The element which contains the modifier text for melee spell attacks.
ReadonlyNAME_CONTAINER: "name-container"A container for a sheet name. The sheet name is usually in input, and its container has some additional styles associated with it. The container typically sits in a sheet header row with other header-related elements.
ReadonlyNAME_HEADER_ROW: "name-header-row"The sheet header row where the sheet name appears.
ReadonlyNPC_ABILITIES_CONTAINER: "npc-abilities-list"A containing element for a series of item lists related to the NPC Abilities tab.
ReadonlyRANGED_SPELL_ATTACK_MOD: "ranged-spell-attack-mod"The element which contains the modifier text for ranged spell attacks.
ReadonlyRESOURCE: "resource"A container for a single resource (first, second, third, etc.).
ReadonlySEARCH_CLEAR: "search-clear"An interactable element that can clear the search input it is associated with.
ReadonlySEARCH_CONTAINER: "search-container"A container for a search input and its search clearing interactable element.
ReadonlySEARCH_INPUT: "search-input"A user input for performing searches.
ReadonlySHEET_LOCK_TOGGLE: "sheet-lock-toggle"A button for toggling whether the sheet is locked or unlocked.
ReadonlySKILL_CONFIGURATION_CONTROL: "skill-configuration-control"An interactable control that can open configuration settings for a target skill.
ReadonlySKILL_CONTAINER: "skill-container"A container for a single skill, including its roller, proficiency toggle, and any other elements related to the skill.
ReadonlySKILL_PROFICIENCY_TOGGLE: "skill-proficiency-toggle"An interactable toggle for skill proficiency.
ReadonlySKILL_ROLLER: "skill-roller"A rollable/interactable element which rolls a skill check.
ReadonlySKILLS_LIST: "skills-list"A list of skills for the target actor.
ReadonlySKILLS_SHOW_PROFICIENT_TOGGLE: "skills-show-proficiency-toggle"An interactable toggle for showing/hiding unproficienct skills.
ReadonlySPELL_ATTACK_MOD: "spell-attack-mod"The element which contains the modifier text for spell attacks in general. This field is shown when melee and ranged spell attack mods are the same.
ReadonlySPELL_DC: "spell-dc"The element which contains spell DC.
ReadonlyTABLE_CELL: "table-cell"A cell in a table row.
ReadonlyTABLE_HEADER_CELL: "table-header-cell"A cell in a table's header row.
ReadonlyTABLE_HEADER_ROW: "table-header-row"The header row in a table.
ReadonlyTABLE_ROW: "table-row"A row in a table.
ReadonlyTOOL_CONFIGURATION_CONTROL: "tool-configuration-control"An interactable control that can open configuration settings for a target tool.
ReadonlyTOOL_CONTAINER: "tool-container"A container for a single tool, including its roller, proficiency toggle, and any other elements related to the tool.
ReadonlyTOOL_PROFICIENCY_TOGGLE: "tool-proficiency-toggle"An interactable toggle for tool proficiency.
ReadonlyTOOL_ROLLER: "tool-roller"A rollable/interactable element which rolls a tool check.
ReadonlyTOOLS_LIST: "tools-list"A list of tools for the target actor.
ReadonlyUTILITY_TOOLBAR: "utility-toolbar"A toolbar that usually sits at the top of a section of content, providing features like search, filtering, etc.
ReadonlyUTILITY_TOOLBAR_COMMAND: "utility-toolbar-command"A toolbar command, usually a button
Various models can be used for API calls.
Svelte-specific integration content. This content is currently experimental and may be subject to change based on integration efforts of other svelte-based modules.
Svelte resources which are directly tied to Tidy's svelte version / runtime.
For svelte + svelte Tidy integration.
The svelte getContext function. Use this function in the context
of a svelte component in order to access Tidy's svelte cache of context data.
Without using this function, any of Tidy's context data set via setContext in its component
hierarchy is not available to an integrating svelte application.
For svelte + svelte Tidy integration.
The svelte mount function. Included for completeness sake,
as a proper use case has not yet been determined.
For svelte + svelte Tidy integration.
The svelte setContext function. Included for completeness sake,
as a proper use case has not yet been determined.
For svelte + svelte Tidy integration.
The svelte SvelteMap class. Included for completeness sake,
as a proper use case has not yet been determined.
For svelte + svelte Tidy integration.
The svelte SvelteSet class. Included for completeness sake,
as a proper use case has not yet been determined.
For svelte + svelte Tidy integration.
The svelte unmount function. Included for completeness sake,
as a proper use case has not yet been determined.
Associates an existing tab by Tab ID with an item subtype.
Note that Details tabs (tab ID details) will not associate properly.
the item subtype key (e.g., loot, equipment, weapon, spell)
the tab ID for the target tab to update
Optionaloptions: ExistingTabAssociationOptionsadditional, optional aspects that can be configured
Creates a selector which allows for locating a part of a given sheet.
a part of the sheet as found in api.constants.SHEET_PARTS
an HTML selector valid for use with JavaScript query selectors
Determines whether the provided sheet is a Tidy 5e Character sheet.
an actor sheet
boolean indicating if the sheet is a Tidy 5e Character sheet
Determines whether the provided sheet is a Tidy 5e Container sheet.
a container sheet
boolean indicating if the sheet is a Tidy 5e Container sheet
Determines whether the provided sheet is a Tidy 5e Group sheet.
a group sheet
boolean indicating if the sheet is a Tidy 5e Group sheet
Determines whether the provided sheet is a Tidy 5e Item sheet.
an item sheet
boolean indicating if the sheet is a Tidy 5e Item sheet
Determines whether the provided sheet is a Tidy 5e NPC sheet.
an actor sheet
boolean indicating if the sheet is a Tidy 5e NPC sheet
Determines whether the provided sheet is any Tidy 5e sheet.
an actor sheet
boolean indicating if the sheet is any Tidy 5e sheet
Determines whether the provided sheet is a Tidy 5e Vehicle sheet.
an actor sheet
boolean indicating if the sheet is a Tidy 5e Vehicle sheet
Adds custom content to all actor sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerActorContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-user"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked custom actor icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 Actor sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerActorHeaderControls({
controls: [
{
icon: 'fas fa-hand-sparkles',
label: 'Say Hello',
async onClickAction() {
ui.notifications.info(`Hello, Foundry!`);
},
},
],
});
});
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerActorHeaderControls({
controls: [
{
icon: 'fas fa-broom',
label: 'Debug Button',
visible() {
return !this.document.collection?.locked;
},
async onClickAction(event) {
ui.notifications.info(
`Logged document data for ${this.document.name} to console for review.`
);
console.log(this.document);
console.log(await this.document.sheet._prepareContext());
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to the available sheet tabs for all actor types that Tidy 5e supports.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Adds custom content to player character sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerCharacterContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-user"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked custom PC icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 Character sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerCharacterHeaderControls({
controls: [
{
icon: 'fas fa-broom',
label: 'Debug Button',
visible() {
return !this.document.collection?.locked;
},
async onClickAction(event) {
ui.notifications.info(
`Logged document data for ${this.document.name} to console for review.`
);
console.log(this.document);
console.log(await this.document.sheet._prepareContext());
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to the available Character sheet sidebar tabs.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Hooks.on('tidy5e-sheet.ready', (api) => {
api.registerCharacterSidebarTab(
new api.models.HtmlTab({
title: 'My Tab',
iconClass: 'fa-solid fa-spaghetti-monster-flying',
html: `
<h1>Hello, world!</h1>
<p>
Behold my sidebar tab, forged in the fires of Mt. Doom and registered in the API via a script in a hook.
The eldritch power of this JavaScript allows you to fire 4 beams which each deal 1d10 force damage.
</p>
`,
tabId: 'my-module-id-registered-character-tab',
})
);
});
Adds a tab to the available Character sheet tabs.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerCharacterTab(
new api.models.HandlebarsTab({
title: 'My Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: 'my-module-id-registered-character-tab',
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
})
);
});
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerCharacterTab(
new api.models.HandlebarsTab({
title: 'The New Inventory Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: api.constants.TAB_ID_CHARACTER_INVENTORY,
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
}),
{
overrideExisting: true,
}
);
});
A tab ID is always required (see TabId).
Optionaloptions: ContentRegistrationOptionsOptionaloptions: ActorTabRegistrationOptionsAdds custom content to group sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerGroupContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-user"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked custom PC icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 Group sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerGroupHeaderControls({
controls: [
{
icon: 'fas fa-broom',
label: 'Debug Button',
visible() {
return !this.document.collection?.locked;
},
async onClickAction(event) {
ui.notifications.info(
`Logged document data for ${this.document.name} to console for review.`
);
console.log(this.document);
console.log(await this.document.sheet._prepareContext());
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to the available Group sheet tabs.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerGroupTab(
new api.models.HandlebarsTab({
title: 'My Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: 'my-module-id-registered-group-tab',
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
})
);
});
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerGroupTab(
new api.models.HandlebarsTab({
title: 'The New Inventory Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: api.constants.TAB_ID_GROUP_INVENTORY,
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
}),
{
overrideExisting: true,
}
);
});
A tab ID is always required (see TabId).
Adds custom content to item sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerItemContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-flask"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked custom item icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 Item sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerItemHeaderControls({
controls: [
{
icon: 'fas fa-coins',
label: 'Take all the coin!',
visible() {
return (
this.document.type === 'container' &&
this.document.actor &&
this.document.isOwner
);
},
async onClickAction(event) {
ui.notifications.info(`Taking all the money out of the bag!`);
const actorCurrency = this.actor.toObject().system.currency;
const containerCurrency = this.document.toObject().system.currency;
for (let [key, value] of Object.entries(containerCurrency)) {
actorCurrency[key] += containerCurrency[key];
containerCurrency[key] = 0;
}
this.actor.update({
system: {
currency: actorCurrency,
},
});
this.document.update({
system: {
currency: containerCurrency,
},
});
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to all relevant item sheets.
the custom tab settings to use when incorporating this tab.
Optionaloptions: ItemTabRegistrationOptionsCustomTabBase for options related to all tabs.
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerItemTab(
new api.models.HandlebarsTab({
title: 'My Item Tab',
tabId: 'my-module-id-my-item-tab',
path: '/modules/my-module-id/my-item-tab.hbs',
enabled: (data) => data.item.type === 'spell',
getData: (data) => {
data['my-extra-data'] = 'Hello, world! 👋';
return data;
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
}));
});
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerItemTab(
new api.models.HtmlTab({
title: "My Item Tab",
tabId: "my-module-id-my-item-tab",
html: "<h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h1>LOREM! IPSUM! FIREBALLLLLL!!</h1><h2>🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥</h2>",
}),
{ autoHeight: true } // 👈 With Auto Height set to `true`, the item window will stretch as tall as it can to match the content height when this tab is viewed.
);
});
Hooks.once('tidy5e-sheet.ready', (api: Tidy5eSheetsApi) => {
api.registerItemTab(
new api.models.HtmlTab({
title: 'My Item Tab',
tabId: 'my-module-id-my-item-tab',
html: '<h1>LO! AND BEHOLD!</h1>',
}),
{
types: ['consumable', 'weapon'],
}
);
});
Hooks.once('tidy5e-sheet.ready', (api: Tidy5eSheetsApi) => {
api.registerItemTab(
new api.models.HtmlTab({
title: 'My Item Tab',
tabId: 'my-module-id-my-item-tab',
html: '<h1>BEHOLD THIS SUBLIME TAB</h1>',
}),
{ types: 'subclass' }
);
});
A tab ID is always required (see TabId).
Adds custom content to NPC sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerNpcContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-user"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked custom NPC icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 NPC sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerNpcHeaderControls({
controls: [
{
icon: 'fas fa-broom',
label: 'Debug Button',
visible() {
return !this.document.collection?.locked;
},
async onClickAction(event) {
ui.notifications.info(
`Logged document data for ${this.document.name} to console for review.`
);
console.log(this.document);
console.log(await this.document.sheet._prepareContext());
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to the available NPC sheet tabs.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerNpcTab(
new api.models.HandlebarsTab({
title: 'My Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: 'my-module-id-registered-npc-tab',
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
})
);
});
A tab ID is always required (see TabId).
Registers additional mappings of tab ID to item types, controlling available options when clicking a "create" button for a given tab.
params for registration (tabId and an array of documentItemTypes)
Optionaloptions: TabIdDocumentItemTypesOptionsoptions for registration (currently mode: 'merge' or 'override')
Adds custom content to vehicle sheets at position relative to selector.
the information necessary to render custom content
Optionaloptions: ContentRegistrationOptionscustom content registration options
void
Hooks.once("tidy5e-sheet.ready", (api) => {
api.registerVehicleContent(
new api.models.HtmlContent({
html: `<a title="Example Button" class="my-custom-icon"><i class="fas fa-user"></i></a>`,
injectParams: {
selector: `[data-tidy-sheet-part="${api.constants.SHEET_PARTS.NAME_CONTAINER}"]`,
position: "beforebegin",
},
onContentReady: (params) => {
console.log("content ready to render", params);
console.log("my content", params.content);
},
onRender: (params) => {
params.element
.querySelector(".my-custom-icon")
.addEventListener("click", () => alert("Clicked Vehicle custom icon"));
},
})
);
});
Registers header controls for all Tidy Application V2 Vehicle sheets.
parameters for registering header controls
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerVehicleHeaderControls({
controls: [
{
icon: 'fas fa-broom',
label: 'Debug Button',
visible() {
return !this.document.collection?.locked;
},
async onClickAction(event) {
ui.notifications.info(
`Logged document data for ${this.document.name} to console for review.`
);
console.log(this.document);
console.log(await this.document.sheet._prepareContext());
},
ownership: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
},
],
});
});
Adds a tab to the available Vehicle sheet tabs.
the information necessary to render a tab
Optionaloptions: ActorTabRegistrationOptionssheet registration options
OptionalincludeAsDefaultTab?: booleanIncludes the registered tab whenever the target sheet has indicated "Use Default" in tab selection settings.
Default: true
Optionallayout?: SheetLayout | SheetLayout[]An optional sheet layout or layouts (default: 'all')
OptionaloverrideExisting?: booleanDetermines whether a newly registered tab should override an existing of the same tab ID. Useful for replacing core Tidy 5e Sheet tabs.
void
Hooks.once('tidy5e-sheet.ready', (api) => {
api.registerVehicleTab(
new api.models.HandlebarsTab({
title: 'My Tab',
path: '/modules/my-module-id/templates/my-handlebars-template.hbs',
tabId: 'my-module-id-registered-vehicle-tab',
getData: async (data) => {
data['my-message'] = 'Hello, world! 🌊🏄♂️';
return Promise.resolve(data);
},
onRender(params) {
const myTab = $(params.tabContentsElement);
myTab.find('.my-control').click(_myHandler.bind(params.app));
},
})
);
});
A tab ID is always required (see TabId).
Wraps the provided HTML so that Tidy will remove the content when handling document changes.
any HTML string that needs to be re-rendered in the style of Foundry Handlebars (usually, this is any time the target document or its embedded documents change).
the original HTML with a transparent element wrapped around which indicates to Tidy that this should be removed and re-rendered.
The intended use of this function is to accompany the use of the tidy5e-sheet.renderActorSheet hook in App V1 (PCs, NPCs, Vehicles)
or the standard sheet render hooks in App V2 (Items, Containers, Groups).
Any content injected through those hooks needs to be wrapped in this way so that the old version
of the HTML can be removed before adding it back in.
Handlebars refreshes content in this way, but for Tidy purposes, the module needs to know when an arbitrary
segment of HTML is meant to be removed. This function provides that information to Tidy for your HTML.
Hooks.on('tidy5e-sheet.renderActorSheet', (app, element, data) => {
const api = game.modules.get('tidy5e-sheet').api;
const actorEmoji = data.actor.system.currency.pp > 0 ? '💹' : '📉';
let iconHtml = api.useHandlebarsRendering(`<h1>${actorEmoji}</h1>`);
// 👆 This HTML looks like `<div style="display: contents;" data-tidy-render-scheme="handlebars"><h1>📉</h1></div>`
// if the actor doesn't have at least 1 platinum.
// Tidy will remove this each time the sheet would normally re-render, and it will add it back.
// When the actor have more than 0 platinum, stonks will rise.
let actorNameElement = element.querySelector(`[data-tidy-field="name"]`);
actorNameElement?.insertAdjacentHTML('afterend', iconHtml);
});
Static_InternalGets an instance of the Tidy 5e Sheets API
instance of the Tidy 5e Sheets API
The Tidy 5e Sheets API. The API becomes available after the hook
tidy5e-sheet.readyis called. When the hook fires, it provides an instance of the API.Example: Getting the API for extending Tidy 5e Sheets
Example: Getting the API from the module
Remarks
It is recommended to retrieve the API from the
tidy5e-sheet.readyhook, since the hook guarantees that the API has been initialized.