diff --git a/Patchnotes.md b/Patchnotes.md
index a1b148c..33c22e9 100644
--- a/Patchnotes.md
+++ b/Patchnotes.md
@@ -1,3 +1,11 @@
+#0.9.0
+- Button on character sheets for opening a search with class and spell level (works on default and TidySheet5e)
+- added filters for subclasses and backgrounds [League-of-Foundry-Developers/compendium-browser#48](https://github.com/League-of-Foundry-Developers/compendium-browser/issues/48)
+- Additional searches for sub-features
+- Merged PR [League-of-Foundry-Developers/compendium-browser#45](https://github.com/League-of-Foundry-Developers/compendium-browser/pull/45)
+- Used more DnD5e loaclization tags. Should be less work to translate, also defaults localization to tag name
+- Fixed item rarity search in Foundry 10+ [League-of-Foundry-Developers/compendium-browser#54](https://github.com/League-of-Foundry-Developers/compendium-browser/issues/54)
+
#0.8.2
- Fixed Class searching for spells - issue: #43
- Fixed Drag-and-Drop error in Foundry V10 - issue: #41
diff --git a/README.md b/README.md
index f5bc204..f09507e 100644
--- a/README.md
+++ b/README.md
@@ -3,25 +3,15 @@ Tired of scrolling compendia? Easily browse and filter for spells, feats, items,
Compendium Browser is faster and better-behaved; **it no longer loads all the compendia into memory on start-up** (which sometimes hung servers because of memory or CPU requirements). Instead, it filters and loads on-demand, as well as giving you a Module Setting to control how many rows are loaded at a time.
-[Patch Notes](https://raw.githubusercontent.com/League-of-Foundry-Developers/compendium-browser/master/Patchnotes.md)
-## v0.8:
-- Compatibility with Foundry V10
-- Added check for "Compendium Folders" module 'phantom' actors (#[CF_tempEntity]) to filter out of NPC list.
-- Fix to handle un-migrated compendiums (they get auto-excluded from the browser even if selected)
-## v0.7:
-- Supports Foundry 0.8.x and Foundry 9
-- Faster searches using Foundry 0.8.x queries (thanks ZoltantheDM!)
-- Faster NPC searches using getIndex() (thanks kyleady!)
-## v0.6:
-- Additional and Optional Features spells from Tasha's
-- Spanish, German translations
## Summary
-* **Authors**: Discord: Spetzel#0103; Felix (felix.mueller.86@web.de); ZoltantheDM
-* **Version**: 0.7.2
-* **Foundry VTT Compatibility**: 0.8.6-9
+* **Authors**: Discord: Spetzel#0103; Felix (felix.mueller.86@web.de); ZoltantheDM (Zoltan#8700); eduardopato41
+* **Version**: 0.9.0
+* **Foundry VTT Compatibility**: 9-10
* **System Compatibility (If applicable)**: dnd5e
* **Translation Support**: en, de (thanks https://github.com/CarnVanBeck), es (thanks https://github.com/JJBocanegra), fr, ja, pt-BR
+[Patch Notes](https://github.com/ZoltanTheDM/compendium-browser/blob/master/Patchnotes.md)
+
## Installation
1. Go to the Add-on Modules tab in Foundry Setup
2. Click Install Module and search for **Compendium Browser** OR paste this link: `https://github.com/League-of-Foundry-Developers/compendium-browser/releases/latest/download/module.json`
@@ -36,9 +26,6 @@ This application enables anyone to add their own custom spell or npc filters via
All filters featured in the app are included in this manner and can be found in the compendium-browser.js at around line 726.
-## Contribution
-If you feel like supporting my work, feel free to leave a tip at my paypal felix.mueller.86@web.de
-
## License
Compendium Browser - a module for Foundry VTT - by Felix Müller is licensed under a Creative Commons Attribution 4.0 International License.
diff --git a/compendium-browser.js b/compendium-browser.js
index cbaa9cb..2c96c90 100644
--- a/compendium-browser.js
+++ b/compendium-browser.js
@@ -284,36 +284,21 @@ class CompendiumBrowser extends Application {
});
this.triggerSort(html, "npc");
- // reset filters and re-render
- //0.4.3: Reset ALL filters because when we do a re-render it affects all tabs
- html.find('#reset-spell-filter').click(ev => {
- this.resetFilters();
- //v0.4.3: Re-render so that we display the filters correctly
- this.refreshList = "spell";
- this.render();
- });
+ for (let tab of ["spell", "feat", "item", "npc"]){
+ // reset filters and re-render
+ //0.4.3: Reset ALL filters because when we do a re-render it affects all tabs
+ html.find(`#reset-${tab}-filter`).click(ev => {
+ this.resetFilters();
+ //v0.4.3: Re-render so that we display the filters correctly
+ this.refreshList = tab;
+ this.render();
+ });
- html.find('#reset-feat-filter').click(ev => {
- this.resetFilters();
- //v0.4.3: Re-render so that we display the filters correctly
- this.refreshList = "feat";
- this.render();
- });
-
- html.find('#reset-item-filter').click(ev => {
- this.resetFilters();
- //v0.4.3: Re-render so that we display the filters correctly
- this.refreshList = "item";
- this.render();
-
- });
-
- html.find('#reset-npc-filter').click(ev => {
- this.resetFilters();
- //v0.4.3: Re-render so that we display the filters correctly
- this.refreshList = "npc";
- this.render();
- });
+ //copy Javascript seach to clipboard
+ html.find(`#copy-search-${tab}`).click(async ev => {
+ this.copySearchToClipboard(tab);
+ });
+ }
// settings
html.find('.settings input').on('change', ev => {
@@ -395,7 +380,13 @@ class CompendiumBrowser extends Application {
value:value
}
}
- this.replaceList(html, browserTab);
+ this.replaceList(html, browserTab);
+
+
+ // console.log(this.spellFilters.activeFilters);
+ // console.log(this.featFilters.activeFilters);
+ // console.log(this.itemFilters.activeFilters);
+ // console.log(this.npcFilters.activeFilters);
});
// multiselect filters
@@ -568,7 +559,7 @@ class CompendiumBrowser extends Application {
const decoratedItem = this.decorateItem(item5e);
- if(decoratedItem && ["feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.featFilters.activeFilters)){
+ if(decoratedItem && ["feat","class","subclass", "background"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.featFilters.activeFilters)){
itemsList[item5e.id] = {
compendium : pack.collection,
name : decoratedItem.name,
@@ -595,7 +586,7 @@ class CompendiumBrowser extends Application {
const decoratedItem = this.decorateItem(item5e);
- if(decoratedItem && !["spell","feat","class"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.itemFilters.activeFilters)){
+ if(decoratedItem && !["spell","feat","class","subclass", "background"].includes(decoratedItem.type) && this.passesFilter(decoratedItem, this.itemFilters.activeFilters)){
itemsList[item5e.id] = {
compendium : pack.collection,
name : decoratedItem.name,
@@ -799,6 +790,10 @@ class CompendiumBrowser extends Application {
cb.replaceList(html, cb.refreshList);
cb.refreshList = null;
+
+ if(CompendiumBrowser.postRender){
+ CompendiumBrowser.postRender();
+ }
}
resetFilters() {
@@ -1084,6 +1079,10 @@ class CompendiumBrowser extends Application {
if (!CompendiumBrowser.isFoundryV10Plus) {
item.hasSave = item5e.hasSave;
}
+ } else if (item.type === 'subclass') {
+ //subclasses dont exist lower then version 10
+ item.classRequirement = [item.system.classIdentifier];
+ item.classRequirementString = item.system.classIdentifier
} else {
// getting pack
let matchedPacks = [];
@@ -1219,6 +1218,7 @@ class CompendiumBrowser extends Application {
return false;
}
} else {
+ if (prop === undefined) return false;
if (filter.value !== undefined && prop !== undefined && prop != filter.value && !(filter.value === true && prop)) {
return false;
}
@@ -1373,23 +1373,36 @@ class CompendiumBrowser extends Application {
//FILTERS - Added on the Ready hook
//0.4.0 Make this async so filters can be added all at once
async addFilter(entityType, category, label, path, type, possibleValues = null, valIsArray = false) {
+
let target = `${entityType}Filters`;
let filter = {};
filter.path = path;
- filter.label = label;
+ filter.labelId = stripSpecialCharacters(label);
+ filter.label = game.i18n.localize(label) ?? label;
filter.type = 'text';
if (['text', 'bool', 'select', 'multiSelect', 'numberCompare'].indexOf(type) !== -1) {
filter[`is${type}`] = true;
filter.type = type;
}
+
if (possibleValues !== null) {
- filter.possibleValues = possibleValues;
+ filter.possibleValueIds = possibleValues;
+
+ filter.possibleValues = Object.keys(possibleValues).reduce(function (acc, current) {
+ acc[current] = game.i18n.localize(possibleValues[current]) ?? possibleValues[current];
+ return acc;
+ }.bind(this),
+ {})
}
filter.valIsArray = valIsArray;
- let catId = category.replace(/\W/g, '');
+ let catId = stripSpecialCharacters(category);
if (this[target].registeredFilterCategorys[catId] === undefined) {
- this[target].registeredFilterCategorys[catId] = {label: category, filters: []};
+ this[target].registeredFilterCategorys[catId] = {
+ label: game.i18n.localize(category) ?? category,
+ labelId: catId,
+ filters: []
+ };
}
this[target].registeredFilterCategorys[catId].filters.push(filter);
@@ -1400,75 +1413,75 @@ class CompendiumBrowser extends Application {
//Foundry v10+ Item#data is now Item#system
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'system.source', 'text');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.lvl"), 'system.level', 'multiSelect', [game.i18n.localize("CMPBrowser.cantip"), 1, 2, 3, 4, 5, 6, 7, 8, 9]);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.school"), 'system.school', 'select', CONFIG.DND5E.spellSchools);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.castingTime"), 'system.activation.type', 'select',
+ this.addSpellFilter("CMPBrowser.general", "DND5E.Source", 'system.source', 'text');
+ this.addSpellFilter("CMPBrowser.general", "DND5E.Level", 'system.level', 'multiSelect', {0:"DND5E.SpellCantrip", 1:"1", 2:"2", 3:"3", 4:"4", 5:"5", 6:"6", 7:"7", 8:"8", 9:"9"});
+ this.addSpellFilter("CMPBrowser.general", "DND5E.SpellSchool", 'system.school', 'select', CONFIG.DND5E.spellSchools);
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.castingTime", 'system.activation.type', 'select',
{
- action: game.i18n.localize("DND5E.Action"),
- bonus: game.i18n.localize("CMPBrowser.bonusAction"),
- reaction: game.i18n.localize("CMPBrowser.reaction"),
- minute: game.i18n.localize("DND5E.TimeMinute"),
- hour: game.i18n.localize("DND5E.TimeHour"),
- day: game.i18n.localize("DND5E.TimeDay")
+ action: "DND5E.Action",
+ bonus: "DND5E.BonusAction",
+ reaction: "DND5E.Reaction",
+ minute: "DND5E.TimeMinute",
+ hour: "DND5E.TimeHour",
+ day: "DND5E.TimeDay"
}
);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.spellType"), 'system.actionType', 'select', CONFIG.DND5E.itemActionTypes);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.spellType", 'system.actionType', 'select', CONFIG.DND5E.itemActionTypes);
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.damageType", 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
//JV-082: Fix for missing "Class" search feature
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.class"), 'classes', 'select',
+ this.addSpellFilter("CMPBrowser.general", "ITEM.TypeClass", 'classes', 'select',
{
- artificer: game.i18n.localize("CMPBrowser.artificer"),
- bard: game.i18n.localize("CMPBrowser.bard"),
- cleric: game.i18n.localize("CMPBrowser.cleric"),
- druid: game.i18n.localize("CMPBrowser.druid"),
- paladin: game.i18n.localize("CMPBrowser.paladin"),
- ranger: game.i18n.localize("CMPBrowser.ranger"),
- sorcerer: game.i18n.localize("CMPBrowser.sorcerer"),
- warlock: game.i18n.localize("CMPBrowser.warlock"),
- wizard: game.i18n.localize("CMPBrowser.wizard"),
+ artificer: "CMPBrowser.artificer",
+ bard: "CMPBrowser.bard",
+ cleric: "CMPBrowser.cleric",
+ druid: "CMPBrowser.druid",
+ paladin: "CMPBrowser.paladin",
+ ranger: "CMPBrowser.ranger",
+ sorcerer: "CMPBrowser.sorcerer",
+ warlock: "CMPBrowser.warlock",
+ wizard: "CMPBrowser.wizard",
}, true
);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.ritual"), 'system.components.ritual', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.concentration"), 'system.components.concentration', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.verbal"), 'system.components.vocal', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.somatic"), 'system.components.somatic', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.material"), 'system.components.material', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.Ritual", 'system.components.ritual', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.Concentration", 'system.components.concentration', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentVerbal", 'system.components.vocal', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentSomatic", 'system.components.somatic', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentMaterial", 'system.components.material', 'bool');
}
else {
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.lvl"), 'data.level', 'multiSelect', [game.i18n.localize("CMPBrowser.cantip"), 1, 2, 3, 4, 5, 6, 7, 8, 9]);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.school"), 'data.school', 'select', CONFIG.DND5E.spellSchools);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.castingTime"), 'data.activation.type', 'select',
+ this.addSpellFilter("CMPBrowser.general", "DND5E.Source", 'data.source', 'text');
+ this.addSpellFilter("CMPBrowser.general", "DND5E.Level", 'data.level', 'multiSelect', {0:"DND5E.SpellCantrip", 1:"1", 2:"2", 3:"3", 4:"4", 5:"5", 6:"6", 7:"7", 8:"8", 9:"9"});
+ this.addSpellFilter("CMPBrowser.general", "DND5E.SpellSchool", 'data.school', 'select', CONFIG.DND5E.spellSchools);
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.castingTime", 'data.activation.type', 'select',
{
- action: game.i18n.localize("DND5E.Action"),
- bonus: game.i18n.localize("CMPBrowser.bonusAction"),
- reaction: game.i18n.localize("CMPBrowser.reaction"),
- minute: game.i18n.localize("DND5E.TimeMinute"),
- hour: game.i18n.localize("DND5E.TimeHour"),
- day: game.i18n.localize("DND5E.TimeDay")
+ action: "DND5E.Action",
+ bonus: "DND5E.BonusAction",
+ reaction: "DND5E.Reaction",
+ minute: "DND5E.TimeMinute",
+ hour: "DND5E.TimeHour",
+ day: "DND5E.TimeDay"
}
);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.spellType"), 'data.actionType', 'select', CONFIG.DND5E.itemActionTypes);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.class"), 'data.classes', 'select',
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.spellType", 'data.actionType', 'select', CONFIG.DND5E.itemActionTypes);
+ this.addSpellFilter("CMPBrowser.general", "CMPBrowser.damageType", 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
+ this.addSpellFilter("CMPBrowser.general", "ITEM.TypeClass", 'data.classes', 'select',
{
- artificer: game.i18n.localize("CMPBrowser.artificer"),
- bard: game.i18n.localize("CMPBrowser.bard"),
- cleric: game.i18n.localize("CMPBrowser.cleric"),
- druid: game.i18n.localize("CMPBrowser.druid"),
- paladin: game.i18n.localize("CMPBrowser.paladin"),
- ranger: game.i18n.localize("CMPBrowser.ranger"),
- sorcerer: game.i18n.localize("CMPBrowser.sorcerer"),
- warlock: game.i18n.localize("CMPBrowser.warlock"),
- wizard: game.i18n.localize("CMPBrowser.wizard"),
+ artificer: "CMPBrowser.artificer",
+ bard: "CMPBrowser.bard",
+ cleric: "CMPBrowser.cleric",
+ druid: "CMPBrowser.druid",
+ paladin: "CMPBrowser.paladin",
+ ranger: "CMPBrowser.ranger",
+ sorcerer: "CMPBrowser.sorcerer",
+ warlock: "CMPBrowser.warlock",
+ wizard: "CMPBrowser.wizard",
}, true
);
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.ritual"), 'data.components.ritual', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.concentration"), 'data.components.concentration', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.verbal"), 'data.components.vocal', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.somatic"), 'data.components.somatic', 'bool');
- this.addSpellFilter(game.i18n.localize("CMPBrowser.components"), game.i18n.localize("CMPBrowser.material"), 'data.components.material', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.Ritual", 'data.components.ritual', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.Concentration", 'data.components.concentration', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentVerbal", 'data.components.vocal', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentSomatic", 'data.components.somatic', 'bool');
+ this.addSpellFilter("DND5E.SpellComponents", "DND5E.ComponentMaterial", 'data.components.material', 'bool');
}
}
@@ -1478,64 +1491,69 @@ class CompendiumBrowser extends Application {
// Feature Filters
//Foundry v10+ Item#data is now Item#system
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addItemFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'system.source', 'text');
+ this.addItemFilter("CMPBrowser.general", "DND5E.Source", 'system.source', 'text');
}
else
{
- this.addItemFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text');
+ this.addItemFilter("CMPBrowser.general", "DND5E.Source", 'data.source', 'text');
}
- this.addItemFilter(game.i18n.localize("CMPBrowser.general"), "Item Type", 'type', 'select', {
- consumable: game.i18n.localize("DND5E.ItemTypeConsumable"),
- backpack: game.i18n.localize("DND5E.ItemTypeContainer"),
- equipment: game.i18n.localize("DND5E.ItemTypeEquipment"),
- loot: game.i18n.localize("DND5E.ItemTypeLoot"),
- tool: game.i18n.localize("DND5E.ItemTypeTool"),
- weapon: game.i18n.localize("DND5E.ItemTypeWeapon")
+ this.addItemFilter("CMPBrowser.general", "Item Type", 'type', 'select', {
+ consumable: "ITEM.TypeConsumable",
+ backpack: "ITEM.TypeContainer",
+ equipment: "ITEM.TypeEquipment",
+ loot: "ITEM.TypeLoot",
+ tool: "ITEM.TypeTool",
+ weapon: "ITEM.TypeWeapon"
});
- this.addItemFilter(game.i18n.localize("CMPBrowser.general"), "Packs", 'matchedPacks', 'select',
+ this.addItemFilter("CMPBrowser.general", "CMPBrowser.ItemsPacks", 'matchedPacks', 'select',
{
- burglar: "Burglar's Pack",
- diplomat: "Diplomat's Pack",
- dungeoneer: "Dungeoneer's Pack",
- entertainer: "Entertainer's Pack",
- explorer: "Explorer's Pack",
- monsterhunter: "Monster Hunter's Pack",
- priest: "Priest's Pack",
- scholar: "Scholar's Pack",
+ burglar: "CMPBrowser.ItemsPacksBurglar",
+ diplomat: "CMPBrowser.ItemsPacksDiplomat",
+ dungeoneer: "CMPBrowser.ItemsPacksDungeoneer",
+ entertainer: "CMPBrowser.ItemsPacksEntertainer",
+ explorer: "CMPBrowser.ItemsPacksExplorer",
+ monsterhunter: "CMPBrowser.ItemsPacksMonsterHunter",
+ priest: "CMPBrowser.ItemsPacksPriest",
+ scholar: "CMPBrowser.ItemsPacksScholar",
}, true
);
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addItemFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'system.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
+ this.addItemFilter("CMPBrowser.GameMechanics", "DND5E.ItemActivationCost", 'system.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
}
else {
- this.addItemFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
+ this.addItemFilter("CMPBrowser.GameMechanics", "DND5E.ItemActivationCost", 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
}
- this.addItemFilter("Game Mechanics", game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
- this.addItemFilter("Game Mechanics", "Uses Resources", 'usesRessources', 'bool');
+ this.addItemFilter("CMPBrowser.GameMechanics", "CMPBrowser.damageType", 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
+ this.addItemFilter("CMPBrowser.GameMechanics", "CMPBrowser.UsesResources", 'usesRessources', 'bool');
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addItemFilter("Item Subtype", "Weapon", 'system.weaponType', 'text', CONFIG.DND5E.weaponTypes);
- this.addItemFilter("Item Subtype", "Equipment", 'system.armor.type', 'text', CONFIG.DND5E.equipmentTypes);
- this.addItemFilter("Item Subtype", "Consumable", 'system.consumableType', 'text', CONFIG.DND5E.consumableTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeWeapon", 'system.weaponType', 'text', CONFIG.DND5E.weaponTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeEquipment", 'system.armor.type', 'text', CONFIG.DND5E.equipmentTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeConsumable", 'system.consumableType', 'text', CONFIG.DND5E.consumableTypes);
}
else {
- this.addItemFilter("Item Subtype", "Weapon", 'data.weaponType', 'text', CONFIG.DND5E.weaponTypes);
- this.addItemFilter("Item Subtype", "Equipment", 'data.armor.type', 'text', CONFIG.DND5E.equipmentTypes);
- this.addItemFilter("Item Subtype", "Consumable", 'data.consumableType', 'text', CONFIG.DND5E.consumableTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeWeapon", 'data.weaponType', 'text', CONFIG.DND5E.weaponTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeEquipment", 'data.armor.type', 'text', CONFIG.DND5E.equipmentTypes);
+ this.addItemFilter("CMPBrowser.ItemSubtype", "ITEM.TypeConsumable", 'data.consumableType', 'text', CONFIG.DND5E.consumableTypes);
}
- //0.7.2c: Fix rarity encoding (uses camelcase names)
- this.addItemFilter("Magic Items", "Rarity", 'data.rarity', 'select',
- {
- common: "Common",
- uncommon: "Uncommon",
- rare: "Rare",
- veryRare: "Very Rare",
- legendary: "Legendary"
- });
+ if (CompendiumBrowser.isFoundryV10Plus) {
+ this.addItemFilter("CMPBrowser.MagicItems", "DND5E.Rarity", 'system.rarity', 'select', CONFIG.DND5E.itemRarity);
+ }
+ else {
+ //0.7.2c: Fix rarity encoding (uses camelcase names)
+ this.addItemFilter("CMPBrowser.MagicItems", "DND5E.Rarity", 'data.rarity', 'select',
+ {
+ common: "DND5E.ItemRarityCommon",
+ uncommon: "DND5E.ItemRarityUncommon",
+ rare: "DND5E.ItemRarityRare",
+ veryRare: "DND5E.ItemRarityVeryRare",
+ legendary: "DND5E.ItemRarityLegendary",
+ });
+ }
}
async addFeatFilters() {
@@ -1543,37 +1561,66 @@ class CompendiumBrowser extends Application {
// Feature Filters
//Foundry v10+ Item#data is now Item#system
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addFeatFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'system.source', 'text');
+ this.addFeatFilter("CMPBrowser.general", "DND5E.Source", 'system.source', 'text');
}
else
{
- this.addFeatFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.source', 'text');
+ this.addFeatFilter("CMPBrowser.general", "DND5E.Source", 'data.source', 'text');
}
- this.addFeatFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.class"), 'classRequirement', 'select',
+ this.addFeatFilter("CMPBrowser.general", "ITEM.TypeClass", 'classRequirement', 'select',
{
- artificer: game.i18n.localize("CMPBrowser.artificer"),
- barbarian: "Barbarian",
- bard: game.i18n.localize("CMPBrowser.bard"),
- cleric: game.i18n.localize("CMPBrowser.cleric"),
- druid: game.i18n.localize("CMPBrowser.druid"),
- fighter: "Fighter",
- monk: "Monk",
- paladin: game.i18n.localize("CMPBrowser.paladin"),
- ranger: game.i18n.localize("CMPBrowser.ranger"),
- rogue: "Rogue",
- sorcerer: game.i18n.localize("CMPBrowser.sorcerer"),
- warlock: game.i18n.localize("CMPBrowser.warlock"),
- wizard: game.i18n.localize("CMPBrowser.wizard")
+ artificer: "CMPBrowser.artificer",
+ barbarian: "CMPBrowser.barbarian",
+ bard: "CMPBrowser.bard",
+ cleric: "CMPBrowser.cleric",
+ druid: "CMPBrowser.druid",
+ fighter: "CMPBrowser.fighter",
+ monk: "CMPBrowser.monk",
+ paladin: "CMPBrowser.paladin",
+ ranger: "CMPBrowser.ranger",
+ rogue: "CMPBrowser.rogue",
+ sorcerer: "CMPBrowser.sorcerer",
+ warlock: "CMPBrowser.warlock",
+ wizard: "CMPBrowser.wizard"
}, true);
+ let featureTypes = {
+ class: "ITEM.TypeClass",
+ feat: "ITEM.TypeFeat",
+ };
+
+ //subclasses don't exist lower then version 10
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addFeatFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'system.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
+ featureTypes.subclass = "ITEM.TypeSubclass";
+ featureTypes.background = "DND5E.Background";
+ }
+
+ this.addFeatFilter("CMPBrowser.general", "CMPBrowser.overall", 'type', 'select',
+ featureTypes
+ , false);
+
+ if (CompendiumBrowser.isFoundryV10Plus) {
+ this.addFeatFilter("CMPBrowser.general", "DND5E.ItemFeatureType", 'system.type.value', 'select',
+ Object.keys(dnd5e.config.featureTypes).reduce(function(acc, current) {
+ acc[current] = dnd5e.config.featureTypes[current].label;
+ return acc;
+ }, {})
+ , false);
+ }
+
+ if (CompendiumBrowser.isFoundryV10Plus) {
+ this.addFeatFilter("CMPBrowser.general", "CMPBrowser.subfeature", 'system.type.subtype', 'select',
+ dnd5e.config.featureTypes.class.subtypes);
+ }
+
+ if (CompendiumBrowser.isFoundryV10Plus) {
+ this.addFeatFilter("CMPBrowser.GameMechanics", "DND5E.ItemActivationCost", 'system.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
}
else {
- this.addFeatFilter("Game Mechanics", game.i18n.localize("DND5E.ItemActivationCost"), 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
+ this.addFeatFilter("CMPBrowser.GameMechanics", "DND5E.ItemActivationCost", 'data.activation.type', 'select', CONFIG.DND5E.abilityActivationTypes);
}
- this.addFeatFilter("Game Mechanics", game.i18n.localize("CMPBrowser.damageType"), 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
- this.addFeatFilter("Game Mechanics", "Uses Resources", 'usesRessources', 'bool');
+ this.addFeatFilter("CMPBrowser.GameMechanics", "CMPBrowser.damageType", 'damageTypes', 'select', CONFIG.DND5E.damageTypes);
+ this.addFeatFilter("CMPBrowser.GameMechanics", "CMPBrowser.UsesResources", 'usesRessources', 'bool');
}
@@ -1583,20 +1630,20 @@ class CompendiumBrowser extends Application {
//Foundry v10+ Actor#data is now Actor#system
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'system.details.source', 'text');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.size"), 'system.traits.size', 'select', CONFIG.DND5E.actorSizes);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasSpells"), 'hasSpells', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasLegAct"), 'system.resources.legact.max', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasLegRes"), 'system.resources.legres.max', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.cr"), 'system.details.cr', 'numberCompare');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.Source", 'system.details.source', 'text');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.Size", 'system.traits.size', 'select', CONFIG.DND5E.actorSizes);
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasSpells", 'hasSpells', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasLegAct", 'system.resources.legact.max', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasLegRes", 'system.resources.legres.max', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.ChallengeRating", 'system.details.cr', 'numberCompare');
}
else {
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("DND5E.Source"), 'data.details.source', 'text');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.size"), 'data.traits.size', 'select', CONFIG.DND5E.actorSizes);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasSpells"), 'hasSpells', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasLegAct"), 'data.resources.legact.max', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.hasLegRes"), 'data.resources.legres.max', 'bool');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.cr"), 'data.details.cr', 'numberCompare');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.Source", 'data.details.source', 'text');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.Size", 'data.traits.size', 'select', CONFIG.DND5E.actorSizes);
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasSpells", 'hasSpells', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasLegAct", 'data.resources.legact.max', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "CMPBrowser.hasLegRes", 'data.resources.legres.max', 'bool');
+ this.addNpcFilter("CMPBrowser.general", "DND5E.ChallengeRating", 'data.details.cr', 'numberCompare');
}
let npcDetailsPath;
//Foundry v10+ Actor#data is now Actor#system
@@ -1611,51 +1658,51 @@ class CompendiumBrowser extends Application {
npcDetailsPath = "data.details.type";
}
- this.addNpcFilter(game.i18n.localize("CMPBrowser.general"), game.i18n.localize("CMPBrowser.creatureType"), npcDetailsPath, 'text', {
- aberration: game.i18n.localize("CMPBrowser.aberration"),
- beast: game.i18n.localize("CMPBrowser.beast"),
- celestial: game.i18n.localize("CMPBrowser.celestial"),
- construct: game.i18n.localize("CMPBrowser.construct"),
- dragon: game.i18n.localize("CMPBrowser.dragon"),
- elemental: game.i18n.localize("CMPBrowser.elemental"),
- fey: game.i18n.localize("CMPBrowser.fey"),
- fiend: game.i18n.localize("CMPBrowser.fiend"),
- giant: game.i18n.localize("CMPBrowser.giant"),
- humanoid: game.i18n.localize("CMPBrowser.humanoid"),
- monstrosity: game.i18n.localize("CMPBrowser.monstrosity"),
- ooze: game.i18n.localize("CMPBrowser.ooze"),
- plant: game.i18n.localize("CMPBrowser.plant"),
- undead: game.i18n.localize("CMPBrowser.undead")
+ this.addNpcFilter("CMPBrowser.general", "DND5E.CreatureType", npcDetailsPath, 'text', {
+ aberration: "DND5E.CreatureAberration",
+ beast: "DND5E.CreatureBeast",
+ celestial: "DND5E.CreatureCelestial",
+ construct: "DND5E.CreatureConstruct",
+ dragon: "DND5E.CreatureDragon",
+ elemental: "DND5E.CreatureElemental",
+ fey: "DND5E.CreatureFey",
+ fiend: "DND5E.CreatureFiend",
+ giant: "DND5E.CreatureGiant",
+ humanoid: "DND5E.CreatureHumanoid",
+ monstrosity: "DND5E.CreatureMonstrosity",
+ ooze: "DND5E.CreatureOoze",
+ plant: "DND5E.CreaturePlant",
+ undead: "DND5E.CreatureUndead"
});
//Foundry v10+ Actor#data is now Actor#system
if (CompendiumBrowser.isFoundryV10Plus) {
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityStr"), 'system.abilities.str.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityDex"), 'system.abilities.dex.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityCon"), 'system.abilities.con.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityInt"), 'system.abilities.int.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityWis"), 'system.abilities.wis.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityCha"), 'system.abilities.cha.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityStr", 'system.abilities.str.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityDex", 'system.abilities.dex.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityCon", 'system.abilities.con.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityInt", 'system.abilities.int.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityWis", 'system.abilities.wis.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityCha", 'system.abilities.cha.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamImm"), 'system.traits.di.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamRes"), 'system.traits.dr.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamVuln"), 'system.traits.dv.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.ConImm"), 'system.traits.ci.value', 'multiSelect', CONFIG.DND5E.conditionTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("CMPBrowser.dmgDealt"), 'damageDealt', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamImm", 'system.traits.di.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamRes", 'system.traits.dr.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamVuln", 'system.traits.dv.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.ConImm", 'system.traits.ci.value', 'multiSelect', CONFIG.DND5E.conditionTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "CMPBrowser.dmgDealt", 'damageDealt', 'multiSelect', CONFIG.DND5E.damageTypes, true);
}
else
{
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityStr"), 'data.abilities.str.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityDex"), 'data.abilities.dex.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityCon"), 'data.abilities.con.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityInt"), 'data.abilities.int.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityWis"), 'data.abilities.wis.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.abilities"), game.i18n.localize("DND5E.AbilityCha"), 'data.abilities.cha.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityStr", 'data.abilities.str.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityDex", 'data.abilities.dex.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityCon", 'data.abilities.con.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityInt", 'data.abilities.int.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityWis", 'data.abilities.wis.value', 'numberCompare');
+ this.addNpcFilter("DND5E.Abilities", "DND5E.AbilityCha", 'data.abilities.cha.value', 'numberCompare');
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamImm"), 'data.traits.di.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamRes"), 'data.traits.dr.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.DamVuln"), 'data.traits.dv.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("DND5E.ConImm"), 'data.traits.ci.value', 'multiSelect', CONFIG.DND5E.conditionTypes, true);
- this.addNpcFilter(game.i18n.localize("CMPBrowser.dmgInteraction"), game.i18n.localize("CMPBrowser.dmgDealt"), 'damageDealt', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamImm", 'data.traits.di.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamRes", 'data.traits.dr.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.DamVuln", 'data.traits.dv.value', 'multiSelect', CONFIG.DND5E.damageTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "DND5E.ConImm", 'data.traits.ci.value', 'multiSelect', CONFIG.DND5E.conditionTypes, true);
+ this.addNpcFilter("CMPBrowser.dmgInteraction", "CMPBrowser.dmgDealt", 'damageDealt', 'multiSelect', CONFIG.DND5E.damageTypes, true);
}
}
@@ -1705,6 +1752,246 @@ class CompendiumBrowser extends Application {
addItemFilter(category, label, path, type, possibleValues = null, valIsArray = false) {
this.addFilter('item', category, label, path, type, possibleValues, valIsArray);
}
+
+ async renderWith(tab="spell", filters=[]){
+
+ //if there isn't a tab error out
+ if(!this[`${tab}Filters`]){
+ ui.notifications.warn(`no tab by name ${tab}`);
+ return
+ }
+
+ this.resetFilters();
+
+ this.refreshList = tab;
+
+ let html = await this.render();
+
+ let activateFilters = filters.reduce((acc, input) => {
+ let filter = this.findFilter(tab, input.section, input.label);
+
+ if (filter){
+ if (input.value){
+ filter.value = input.value;
+ }
+ else if(input.values){
+ filter.values = input.values;
+ }
+ else{
+ ui.notifications.warn(`no value(s) in filter:${tab} ${input.section}, ${input.label}`);
+ }
+
+ acc[stripSpecialCharacters(filter.path)] = filter;
+ }
+ else{
+ ui.notifications.warn(`filter not found: tab:${tab} ${input.section}, ${input.label}.`);
+ }
+
+ return acc;
+ },
+ {})
+
+ this[`${tab}Filters`].activeFilters = activateFilters;
+
+ //wait for after the afterRender function to change tabs
+ //this avoids some errors when initially opening the window
+ CompendiumBrowser.postRender = async ()=>{
+
+ CompendiumBrowser.postRender = ()=>{};
+
+ await html.activateTab(tab);
+
+ for (let input of filters){
+ let filter = this.findFilter(tab, input.section, input.label);
+
+ if (!filter){
+ continue;
+ }
+
+ const typeMap = {
+ select:"select",
+ bool: "select",
+ text: "input",
+ }
+
+ if (filter.type in typeMap){
+ let component = html.element.find(`div.tab.active #${input.section}-${input.label} ${typeMap[filter.type]}`)
+
+ component[0].value = input.value;
+ }
+ else if (filter.type == "multiSelect"){
+ let components = html.element.find(`div.tab.active #${input.section}-${input.label}`)
+
+ for (let v of input.values){
+ let c = components.find(`input[data-value=${v}]`)
+ c.prop( "checked", true );
+ }
+ }
+ else{
+ ui.notifications.warn(`Unknown filter type?`);
+ console.log(filter)
+ }
+
+ }
+
+ };
+
+ this.render(true);
+
+ return this
+ }
+
+ findFilter(type, category, label){
+ let target = `${type}Filters`;
+ let catId = stripSpecialCharacters(category);
+
+ if (!this[target].registeredFilterCategorys[catId]){
+ return;
+ }
+
+ let filter = this[target].registeredFilterCategorys[catId].filters.
+ find(x => x.labelId == label)
+
+ if (!filter){
+ return;
+ }
+
+ return {
+ path: filter.path,
+ type: filter.type,
+ valIsArray: filter.valIsArray,
+ }
+ }
+
+ async copySearchToClipboard(tab){
+ const text = this.getSearchText(tab)
+
+ try {
+ await navigator.clipboard.writeText(text);
+ ui.notifications.info("Javascript Copied to clipboard")
+ } catch (err) {
+ ui.notifications.warn("failed to copy javascript to clipboard, check logs for string")
+ console.error('Failed to copy: ', err);
+ console.log(text);
+ }
+ }
+
+ getSearchText(tab){
+ const target = `${tab}Filters`
+
+ //map active filters to their labels
+ let output = Object.values(this[target].activeFilters).map(filter => {
+ //find Filters from paths
+ let out = this.findFilterR(target, filter)
+
+ if(filter.value){
+ out.value = filter.value;
+ }
+ else if(filter.values){
+ out.values = filter.values;
+ }
+
+ return out;
+ })
+
+ const strOut = `game.compendiumBrowser.renderWith("${tab}", ${JSON.stringify(output)})`
+
+ return strOut;
+ }
+
+ findFilterR(target, filterTarget){
+ for (let cat of Object.keys(this[target].registeredFilterCategorys)){
+ for (let filter of this[target].registeredFilterCategorys[cat].filters){
+ if (filterTarget.path == filter.path){
+ return {section:`${cat}`, label:`${filter.labelId}`}
+ }
+ }
+ }
+
+ ui.notifications.warn("Could not find the filter!!")
+ console.warn(filterTarget)
+ return;
+ }
+
+ static async addTidySheetButton(cb, html, actor){
+
+ await html.find('.spell-browser-btn').remove();
+
+ let tabBar = html.find("div.tab.spellbook .spellcasting-ability")
+ // console.log(tabBar)
+ const cbButton = $(`