mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-03-07 22:46:12 +01:00
FEAT: create FilterMenu class
FEAT: add FilterMenu to CharacterSheet
This commit is contained in:
parent
19cc10a3c9
commit
4e7c46bb3d
6 changed files with 307 additions and 25 deletions
|
|
@ -6,6 +6,7 @@ import DaggerheartSheet from './daggerheart-sheet.mjs';
|
|||
import { abilities } from '../../config/actorConfig.mjs';
|
||||
import DhlevelUp from '../levelup.mjs';
|
||||
import DhCharacterCreation from '../characterCreation.mjs';
|
||||
import FilterMenu from '../ux/property-filter.mjs';
|
||||
|
||||
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||
const { TextEditor } = foundry.applications.ux;
|
||||
|
|
@ -215,6 +216,8 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
await super._onFirstRender(context, options);
|
||||
|
||||
this._createContextMenues();
|
||||
this._createFilterMenus();
|
||||
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
@ -440,7 +443,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Search Filter */
|
||||
/* Filter Tracking */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
|
|
@ -450,12 +453,33 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
#search = {};
|
||||
|
||||
/**
|
||||
* Track which item IDs are currently displayed due to a search filter.
|
||||
* @type {{ inventory: Set<string>, loadout: Set<string> }}
|
||||
* The currently active search filter.
|
||||
* @type {FilterMenu}
|
||||
*/
|
||||
#menu = {};
|
||||
|
||||
/**
|
||||
* Tracks which item IDs are currently displayed, organized by filter type and section.
|
||||
* @type {{
|
||||
* inventory: {
|
||||
* search: Set<string>,
|
||||
* menu: Set<string>
|
||||
* },
|
||||
* loadout: {
|
||||
* search: Set<string>,
|
||||
* menu: Set<string>
|
||||
* },
|
||||
* }}
|
||||
*/
|
||||
#filteredItems = {
|
||||
inventory: new Set(),
|
||||
loadout: new Set()
|
||||
inventory: {
|
||||
search: new Set(),
|
||||
menu: new Set(),
|
||||
},
|
||||
loadout: {
|
||||
search: new Set(),
|
||||
menu: new Set(),
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -503,15 +527,14 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
* @protected
|
||||
*/
|
||||
_onSearchFilterInventory(event, query, rgx, html) {
|
||||
this.#filteredItems.inventory.clear();
|
||||
this.#filteredItems.inventory.search.clear();
|
||||
|
||||
for (const ul of html.querySelectorAll('.items-list')) {
|
||||
for (const li of ul.querySelectorAll('.inventory-item')) {
|
||||
const item = this.document.items.get(li.dataset.itemId);
|
||||
const match = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
|
||||
if (match) this.#filteredItems.inventory.add(item.id);
|
||||
li.hidden = !match;
|
||||
}
|
||||
for (const li of html.querySelectorAll('.inventory-item')) {
|
||||
const item = this.document.items.get(li.dataset.itemId);
|
||||
const matchesSearch = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
|
||||
if (matchesSearch) this.#filteredItems.inventory.search.add(item.id);
|
||||
const { menu } = this.#filteredItems.inventory;
|
||||
li.hidden = !(menu.has(item.id) && matchesSearch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,18 +547,111 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
* @protected
|
||||
*/
|
||||
_onSearchFilterCard(event, query, rgx, html) {
|
||||
this.#filteredItems.loadout.clear();
|
||||
this.#filteredItems.loadout.search.clear();
|
||||
|
||||
const elements = html.querySelectorAll('.items-list .inventory-item, .card-list .card-item');
|
||||
|
||||
for (const li of elements) {
|
||||
for (const li of html.querySelectorAll('.items-list .inventory-item, .card-list .card-item')) {
|
||||
const item = this.document.items.get(li.dataset.itemId);
|
||||
const match = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
|
||||
if (match) this.#filteredItems.loadout.add(item.id);
|
||||
li.hidden = !match;
|
||||
const matchesSearch = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
|
||||
if (matchesSearch) this.#filteredItems.loadout.search.add(item.id);
|
||||
const { menu } = this.#filteredItems.loadout;
|
||||
li.hidden = !(menu.has(item.id) && matchesSearch);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Filter Menus */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
_createFilterMenus() {
|
||||
//Menus could be a application option if needed
|
||||
const menus = [
|
||||
{
|
||||
key: 'inventory',
|
||||
container: '[data-application-part="inventory"]',
|
||||
content: '.items-section',
|
||||
callback: this._onMenuFilterInventory.bind(this),
|
||||
target: '.filter-button',
|
||||
filters: [{
|
||||
group: "Type",
|
||||
name: "Weapons",
|
||||
filter: {
|
||||
field: "type",
|
||||
operator: foundry.applications.ux.SearchFilter.OPERATORS.EQUALS,
|
||||
value: "weapon",
|
||||
}
|
||||
}, {
|
||||
group: "Type",
|
||||
name: "Armor",
|
||||
filter: {
|
||||
field: "type",
|
||||
operator: foundry.applications.ux.SearchFilter.OPERATORS.EQUALS,
|
||||
value: "armor",
|
||||
}
|
||||
}],
|
||||
},
|
||||
{
|
||||
key: 'loadout',
|
||||
container: '[data-application-part="loadout"]',
|
||||
content: '.items-section',
|
||||
callback: this._onMenuFilterLoadout.bind(this),
|
||||
target: '.filter-button',
|
||||
filters: [],
|
||||
}
|
||||
];
|
||||
|
||||
menus.forEach(m => {
|
||||
const container = this.element.querySelector(m.container);
|
||||
this.#menu[m.key] = new FilterMenu(container, m.target, m.filters, m.callback, {
|
||||
contentSelector: m.content,
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback when filters change
|
||||
* @param {PointerEvent} event
|
||||
* @param {HTMLElement} html
|
||||
* @param {import('../ux/property-filter.mjs').FilterItem[]} filters
|
||||
*/
|
||||
_onMenuFilterInventory(event, html, filters) {
|
||||
this.#filteredItems.inventory.menu.clear();
|
||||
|
||||
for (const li of html.querySelectorAll('.inventory-item')) {
|
||||
const item = this.document.items.get(li.dataset.itemId);
|
||||
|
||||
const matchesMenu = filters.length === 0 ||
|
||||
filters.some(f => foundry.applications.ux.SearchFilter.evaluateFilter(item, f));
|
||||
if (matchesMenu) this.#filteredItems.inventory.menu.add(item.id);
|
||||
|
||||
const { search } = this.#filteredItems.inventory;
|
||||
li.hidden = !(search.has(item.id) && matchesMenu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when filters change
|
||||
* @param {PointerEvent} event
|
||||
* @param {HTMLElement} html
|
||||
* @param {import('../ux/property-filter.mjs').FilterItem[]} filters
|
||||
*/
|
||||
_onMenuFilterLoadout(event, html, filters) {
|
||||
this.#filteredItems.loadout.menu.clear();
|
||||
|
||||
for (const li of html.querySelectorAll('.items-list .inventory-item, .card-list .card-item')) {
|
||||
const item = this.document.items.get(li.dataset.itemId);
|
||||
|
||||
const matchesMenu = filters.length === 0 ||
|
||||
filters.some(f => foundry.applications.ux.SearchFilter.evaluateFilter(item, f));
|
||||
if (matchesMenu) this.#filteredItems.loadout.menu.add(item.id);
|
||||
|
||||
const { search } = this.#filteredItems.loadout;
|
||||
li.hidden = !(search.has(item.id) && matchesMenu);
|
||||
}
|
||||
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async mapFeatureType(data, configType) {
|
||||
|
|
@ -815,9 +931,8 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
|
|||
const cls = getDocumentClass('ChatMessage');
|
||||
const systemData = {
|
||||
name: game.i18n.localize('DAGGERHEART.General.Experience.Single'),
|
||||
description: `${experience.description} ${
|
||||
experience.total < 0 ? experience.total : `+${experience.total}`
|
||||
}`
|
||||
description: `${experience.description} ${experience.total < 0 ? experience.total : `+${experience.total}`
|
||||
}`
|
||||
};
|
||||
const msg = new cls({
|
||||
type: 'abilityUse',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue