Files
vermine2047/module/system/applications.mjs
T
uberwald 0189f62734 fix: importer foundry.applications.api et utiliser _onRender dans les pickers AppV2
- applications.mjs: import HandlebarsApplicationMixin/ApplicationV2 from
  foundry.applications.api (they are not globals in Foundry v14), fixing
  'ReferenceError: HandlebarsApplicationMixin is not defined'
- Replace activateListeners(html) with _onRender(context, options) and
  this.element — AppV2 does not call activateListeners
- TraitSelector: remove recursive render(true) in _validateTraits
- fight.mjs: VermineCombatTracker same _onRender conversion
2026-08-01 21:33:38 +02:00

193 lines
5.0 KiB
JavaScript

const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
export class TotemPicker extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(linkEl, actor) {
super();
this.linkEl = linkEl;
this.actor = actor;
}
static get DEFAULT_OPTIONS() {
return {
id: "TOTEM_PICKER",
position: { width: 800, height: 800 },
window: { title: game.i18n.localize("VERMINE.totem_picker"), resizable: true }
};
}
static PARTS = {
main: {
template: 'systems/vermine2047/templates/applications/choose-totem.hbs'
}
};
_prepareContext() {
return { config: CONFIG.VERMINE };
}
_onRender(context, options) {
super._onRender(context, options);
this.element.querySelectorAll('.totem').forEach(el => {
el.addEventListener('click', event => {
const link = event.target.closest('a');
if (!link?.dataset.totem) return;
this.actor.update({ 'system.identity.totem': link.dataset.totem });
this.close();
});
});
}
}
export class ActorPicker extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(linkEl, actor) {
super();
this.linkEl = linkEl;
this.actor = actor;
}
static get DEFAULT_OPTIONS() {
return {
id: "ACTOR_PICKER",
position: { width: 600, height: 350 },
window: { title: game.i18n.localize("VERMINE.actor_picker"), resizable: true }
};
}
static PARTS = {
main: {
template: 'systems/vermine2047/templates/applications/choose-actor.hbs'
}
};
_prepareContext() {
const npcs = game.actors.filter(a => a.type == "npc");
const characters = game.actors.filter(a => a.type == "character");
const all = game.actors.filter(a => a.type == "npc" || a.type == 'character');
const type = this.linkEl.dataset.type;
let actorsList = [];
if (type == 'members') {
actorsList = characters;
} else if (type == 'relations') {
actorsList = npcs;
} else {
actorsList = all;
}
return {
config: CONFIG.VERMINE,
actorsList: actorsList
};
}
_onRender(context, options) {
super._onRender(context, options);
this.element.querySelectorAll('.actor').forEach(el => {
el.addEventListener('click', async event => {
const div = event.target.closest('div');
const actorId = div?.dataset.actorId;
const type = this.linkEl.dataset.type;
if (!actorId) return;
let actorsList = [];
if (type == 'members') {
actorsList = foundry.utils.duplicate(this.actor.system.members || []);
} else if (type == 'encounters') {
actorsList = foundry.utils.duplicate(this.actor.system.encounters || []);
}
if (!Array.isArray(actorsList)) {
actorsList = [];
}
if (!actorsList.includes(actorId)) {
actorsList.push(actorId);
}
if (type == 'members') {
await this.actor.update({ 'system.members': actorsList });
} else if (type == 'encounters') {
await this.actor.update({ 'system.encounters': actorsList });
}
this.close();
});
});
}
}
export class TraitSelector extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(targetItem) {
super();
this.targetItem = targetItem;
this.traits = CONFIG.VERMINE.traits;
}
static get DEFAULT_OPTIONS() {
return {
id: "TRAIT_SELECTOR",
position: { width: 500, height: 500 },
window: { title: game.i18n.localize("VERMINE.traits_selector"), resizable: true },
classes: ["vermine2047", "trait-selector"]
};
}
static PARTS = {
main: {
template: 'systems/vermine2047/templates/applications/choose-traits.hbs'
}
};
_prepareContext() {
return {
traits: this.traits,
item: this.targetItem
};
}
_onRender(context, options) {
super._onRender(context, options);
this._validateTraits(this.element);
this.element.querySelectorAll('input').forEach(el => {
el.addEventListener('change', ev => this._onChangeInput(ev));
});
}
_validateTraits(html) {
const checks = html.querySelectorAll("input.trait-selector");
for (const inp of checks) {
if (this.targetItem.system.traits[inp.dataset.trait]) {
if (inp.type == "checkbox") {
inp.checked = true;
}
}
}
}
async _onChangeInput(ev) {
const el = ev.currentTarget;
const traitKey = el.dataset.trait;
const traitValue = parseInt(el.value) || null;
const traits = this.targetItem.system.traits || {};
if (el.classList.contains('trait-selector')) {
if (!traits[traitKey]) {
await this.targetItem.update({ [`system.traits.${traitKey}`]: this.traits[traitKey] });
} else {
await this.targetItem.update({ [`system.traits.${traitKey}`]: null });
}
}
if (traitValue) {
el.closest("label").querySelector('.trait-selector').checked = true;
} else {
el.closest("label").querySelector('.trait-selector').checked = false;
}
this.render(true);
}
}