foundry-sw5e/module/apps/proficiency-selector.js
supervj 5bb253d9c3 Update Core to 1.4.1
Update Core to 1.4.1 and internal Version to 1.4.1.R1-A8
2021-08-06 16:38:15 -04:00

120 lines
4.1 KiB
JavaScript

import TraitSelector from "./trait-selector.js";
/**
* An application for selecting proficiencies with categories that can contain children.
*
* @extends {TraitSelector}
*/
export default class ProficiencySelector extends TraitSelector {
/** @inheritdoc */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
title: "Actor Proficiency Selection",
type: "",
sortCategories: false
});
}
/* -------------------------------------------- */
/** @inheritdoc */
async getData() {
const attr = foundry.utils.getProperty(this.object.data, this.attribute);
const value = this.options.valueKey ? foundry.utils.getProperty(attr, this.options.valueKey) ?? [] : attr;
this.options.choices = CONFIG.SW5E[`${this.options.type}Proficiencies`];
const data = super.getData();
const pack = game.packs.get(CONFIG.SW5E.sourcePacks.ITEMS);
const ids = CONFIG.SW5E[`${this.options.type}Ids`];
const map = CONFIG.SW5E[`${this.options.type}ProficienciesMap`];
if (ids !== undefined) {
const typeProperty = this.options.type !== "armor" ? `${this.options.type}Type` : `armor.type`;
for (const [key, id] of Object.entries(ids)) {
const item = await pack.getDocument(id);
let type = foundry.utils.getProperty(item.data.data, typeProperty);
if (map && map[type]) type = map[type];
const entry = {
label: item.name,
chosen: attr ? value.includes(key) : false
};
if (data.choices[type] === undefined) {
data.choices[key] = entry;
} else {
if (data.choices[type].children === undefined) {
data.choices[type].children = {};
}
data.choices[type].children[key] = entry;
}
}
}
if (this.options.type === "tool") {
data.choices["vehicle"].children = Object.entries(CONFIG.SW5E.vehicleTypes).reduce((obj, [key, label]) => {
obj[key] = {
label: label,
chosen: attr ? value.includes(key) : false
};
return obj;
}, {});
}
if (this.options.sortCategories) data.choices = this._sortObject(data.choices);
for (const category of Object.values(data.choices)) {
if (!category.children) continue;
category.children = this._sortObject(category.children);
}
return data;
}
/* -------------------------------------------- */
/**
* Take the provided object and sort by the "label" property.
*
* @param {object} object Object to be sorted.
* @return {object} Sorted object.
* @private
*/
_sortObject(object) {
return Object.fromEntries(Object.entries(object).sort((lhs, rhs) => lhs[1].label.localeCompare(rhs[1].label)));
}
/* -------------------------------------------- */
/** @inheritdoc */
activateListeners(html) {
super.activateListeners(html);
for (const checkbox of html[0].querySelectorAll("input[type='checkbox']")) {
if (checkbox.checked) this._onToggleCategory(checkbox);
}
}
/* -------------------------------------------- */
/** @inheritdoc */
async _onChangeInput(event) {
super._onChangeInput(event);
if (event.target.tagName === "INPUT") this._onToggleCategory(event.target);
}
/* -------------------------------------------- */
/**
* Enable/disable all children when a category is checked.
*
* @param {HTMLElement} checkbox Checkbox that was changed.
* @private
*/
_onToggleCategory(checkbox) {
const children = checkbox.closest("li")?.querySelector("ol");
if (!children) return;
for (const child of children.querySelectorAll("input[type='checkbox']")) {
child.checked = child.disabled = checkbox.checked;
}
}
}