Files
5etools-mirror-2.github.io/js/items.js
TheGiddyLimit 8117ebddc5 v1.198.1
2024-01-01 19:34:49 +00:00

467 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
class ItemsSublistManager extends SublistManager {
constructor () {
super({
sublistListOptions: {
fnSort: PageFilterItems.sortItems,
},
isSublistItemsCountable: true,
});
this._sublistCurrencyConversion = null;
this._sublistCurrencyDisplayMode = null;
this._$totalWeight = null;
this._$totalValue = null;
this._$totalItems = null;
}
async pCreateSublist () {
[this._sublistCurrencyConversion, this._sublistCurrencyDisplayMode] = await Promise.all([
StorageUtil.pGetForPage("sublistCurrencyConversion"),
StorageUtil.pGetForPage("sublistCurrencyDisplayMode"),
]);
return super.pCreateSublist();
}
static get _ROW_TEMPLATE () {
return [
new SublistCellTemplate({
name: "Name",
css: "bold col-6 pl-0",
colStyle: "",
}),
new SublistCellTemplate({
name: "Weight",
css: "ve-text-center col-2",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "Cost",
css: "ve-text-center col-2",
colStyle: "text-center",
}),
new SublistCellTemplate({
name: "Number",
css: "ve-text-center col-2 pr-0",
colStyle: "text-center",
}),
];
}
pGetSublistItem (item, hash, {count = 1} = {}) {
const cellsText = [
item.name,
Parser.itemWeightToFull(item, true) || "\u2014",
item.value || item.valueMult ? Parser.itemValueToFullMultiCurrency(item, {isShortForm: true}).replace(/ +/g, "\u00A0") : "\u2014",
];
const $dispCount = $(`<span class="ve-text-center col-2 pr-0">${count}</span>`);
const $ele = $$`<div class="lst__row lst__row--sublist ve-flex-col">
<a href="#${hash}" class="lst--border lst__row-inner">
${this.constructor._getRowCellsHtml({values: cellsText, templates: this.constructor._ROW_TEMPLATE.slice(0, 3)})}
${$dispCount}
</a>
</div>`
.contextmenu(evt => this._handleSublistItemContextMenu(evt, listItem))
.click(evt => this._listSub.doSelect(listItem, evt));
const listItem = new ListItem(
hash,
$ele,
item.name,
{
hash,
source: Parser.sourceJsonToAbv(item.source),
weight: Parser.weightValueToNumber(item.weight),
cost: item.value || 0,
},
{
count,
$elesCount: [$dispCount],
entity: item,
mdRow: [...cellsText, ({listItem}) => listItem.data.count],
},
);
return listItem;
}
_onSublistChange () {
this._$totalWeight = this._$totalWeight || $(`#totalweight`);
this._$totalValue = this._$totalValue || $(`#totalvalue`);
this._$totalItems = this._$totalItems || $(`#totalitems`);
let weight = 0;
let value = 0;
let cntItems = 0;
const availConversions = new Set();
this._listSub.items.forEach(it => {
const {data: {entity: item}} = it;
if (item.currencyConversion) availConversions.add(item.currencyConversion);
const count = it.data.count;
cntItems += it.data.count;
if (item.weight) weight += Number(item.weight) * count;
if (item.value) value += item.value * count;
});
this._$totalWeight.text(Parser.itemWeightToFull({weight}, true));
this._$totalItems.text(cntItems);
if (availConversions.size) {
this._$totalValue
.text(Parser.itemValueToFullMultiCurrency({value, currencyConversion: this._sublistCurrencyConversion}))
.off("click")
.click(async () => {
const values = ["(Default)", ...[...availConversions].sort(SortUtil.ascSortLower)];
const defaultSel = values.indexOf(this._sublistCurrencyConversion);
const userSel = await InputUiUtil.pGetUserEnum({
values,
isResolveItem: true,
default: ~defaultSel ? defaultSel : 0,
title: "Select Currency Conversion Table",
fnDisplay: it => it === null ? values[0] : it,
});
if (userSel == null) return;
this._sublistCurrencyConversion = userSel === values[0] ? null : userSel;
await StorageUtil.pSetForPage("sublistCurrencyConversion", this._sublistCurrencyConversion);
this._onSublistChange();
});
return;
}
this._$totalValue
.text(this._getTotalValueText({value}) || "\u2014")
.off("click")
.click(async () => {
const defaultSel = this.constructor._TOTAL_VALUE_MODES.indexOf(this._sublistCurrencyDisplayMode);
const userSel = await InputUiUtil.pGetUserEnum({
values: this.constructor._TOTAL_VALUE_MODES,
isResolveItem: true,
default: ~defaultSel ? defaultSel : 0,
title: "Select Display Mode",
fnDisplay: it => it === null ? this.constructor._TOTAL_VALUE_MODES[0] : it,
});
if (userSel == null) return;
this._sublistCurrencyDisplayMode = userSel === this.constructor._TOTAL_VALUE_MODES[0] ? null : userSel;
await StorageUtil.pSetForPage("sublistCurrencyDisplayMode", this._sublistCurrencyDisplayMode);
this._onSublistChange();
});
}
static _TOTAL_VALUE_MODE_EXACT_COINAGE = "Exact Coinage";
static _TOTAL_VALUE_MODE_LOWEST_COMMON = "Lowest Common Currency";
static _TOTAL_VALUE_MODE_GOLD = "Gold";
static _TOTAL_VALUE_MODES = [
this._TOTAL_VALUE_MODE_EXACT_COINAGE,
this._TOTAL_VALUE_MODE_LOWEST_COMMON,
this._TOTAL_VALUE_MODE_GOLD,
];
_getTotalValueText ({value}) {
switch (this._sublistCurrencyDisplayMode) {
case this.constructor._TOTAL_VALUE_MODE_LOWEST_COMMON: return Parser.itemValueToFull({value});
case this.constructor._TOTAL_VALUE_MODE_GOLD: {
return value ? `${Number((Parser.DEFAULT_CURRENCY_CONVERSION_TABLE.find(it => it.coin === "gp").mult * value).toFixed(2))} gp` : "";
}
default: {
const CURRENCIES = ["gp", "sp", "cp"];
const coins = {cp: value};
CurrencyUtil.doSimplifyCoins(coins);
return CURRENCIES.filter(it => coins[it]).map(it => `${coins[it].toLocaleString(undefined, {maximumFractionDigits: 5})} ${it}`).join(", ");
}
}
}
}
class ItemsPage extends ListPage {
constructor () {
const pFnGetFluff = Renderer.item.pGetFluff.bind(Renderer.item);
super({
dataSource: DataUtil.item.loadJSON.bind(DataUtil.item),
prereleaseDataSource: DataUtil.item.loadPrerelease.bind(DataUtil.item),
brewDataSource: DataUtil.item.loadBrew.bind(DataUtil.item),
pFnGetFluff,
pageFilter: new PageFilterItems(),
dataProps: ["item"],
bookViewOptions: {
namePlural: "items",
pageTitle: "Items Book View",
propMarkdown: "item",
},
tableViewOptions: {
title: "Items",
colTransforms: {
name: UtilsTableview.COL_TRANSFORM_NAME,
source: UtilsTableview.COL_TRANSFORM_SOURCE,
rarity: {name: "Rarity"},
_type: {name: "Type", transform: it => [it._typeHtml || "", it._subTypeHtml || ""].filter(Boolean).join(", ")},
_attunement: {name: "Attunement", transform: it => it._attunement ? it._attunement.slice(1, it._attunement.length - 1) : ""},
_properties: {name: "Properties", transform: it => Renderer.item.getDamageAndPropertiesText(it).filter(Boolean).join(", ")},
_weight: {name: "Weight", transform: it => Parser.itemWeightToFull(it)},
_value: {name: "Value", transform: it => Parser.itemValueToFullMultiCurrency(it)},
_entries: {name: "Text", transform: (it) => Renderer.item.getRenderedEntries(it, {isCompact: true}), flex: 3},
},
},
isMarkdownPopout: true,
propEntryData: "item",
listSyntax: new ListSyntaxItems({fnGetDataList: () => this._dataList, pFnGetFluff}),
});
this._mundaneList = null;
this._magicList = null;
}
get _bindOtherButtonsOptions () {
return {
other: [
this._bindOtherButtonsOptions_openAsSinglePage({slugPage: "items", fnGetHash: () => Hist.getHashParts()[0]}),
].filter(Boolean),
};
}
get primaryLists () { return [this._mundaneList, this._magicList]; }
getListItem (item, itI, isExcluded) {
const hash = UrlUtil.autoEncodeHash(item);
if (Renderer.item.isExcluded(item, {hash})) return null;
if (item.noDisplay) return null;
Renderer.item.enhanceItem(item);
this._pageFilter.mutateAndAddToFilters(item, isExcluded);
const source = Parser.sourceJsonToAbv(item.source);
const type = item._typeListText.join(", ").toTitleCase();
if (item._fIsMundane) {
const eleLi = e_({
tag: "div",
clazz: `lst__row ve-flex-col ${isExcluded ? "lst__row--blocklisted" : ""}`,
click: (evt) => this._mundaneList.doSelect(listItem, evt),
contextmenu: (evt) => this._openContextMenu(evt, this._mundaneList, listItem),
children: [
e_({
tag: "a",
href: `#${hash}`,
clazz: "lst--border lst__row-inner",
children: [
e_({tag: "span", clazz: `col-3-5 pl-0 bold`, text: item.name}),
e_({tag: "span", clazz: `col-4-5`, text: type}),
e_({tag: "span", clazz: `col-1-5 ve-text-center`, text: `${item.value || item.valueMult ? Parser.itemValueToFullMultiCurrency(item, {isShortForm: true}).replace(/ +/g, "\u00A0") : "\u2014"}`}),
e_({tag: "span", clazz: `col-1-5 ve-text-center`, text: Parser.itemWeightToFull(item, true) || "\u2014"}),
e_({
tag: "span",
clazz: `col-1 ve-text-center ${Parser.sourceJsonToColor(item.source)} pr-0`,
style: Parser.sourceJsonToStylePart(item.source),
title: `${Parser.sourceJsonToFull(item.source)}${Renderer.utils.getSourceSubText(item)}`,
text: source,
}),
],
}),
],
});
const listItem = new ListItem(
itI,
eleLi,
item.name,
{
hash,
source,
type,
cost: item.value || 0,
weight: Parser.weightValueToNumber(item.weight),
},
{
isExcluded,
},
);
return {mundane: listItem};
} else {
const eleLi = e_({
tag: "div",
clazz: `lst__row ve-flex-col ${isExcluded ? "lst__row--blocklisted" : ""}`,
click: (evt) => this._magicList.doSelect(listItem, evt),
contextmenu: (evt) => this._openContextMenu(evt, this._magicList, listItem),
children: [
e_({
tag: "a",
href: `#${hash}`,
clazz: "lst--border lst__row-inner",
children: [
e_({tag: "span", clazz: `col-3-5 pl-0 bold`, text: item.name}),
e_({tag: "span", clazz: `col-4`, text: type}),
e_({tag: "span", clazz: `col-1-5 ve-text-center`, text: Parser.itemWeightToFull(item, true) || "\u2014"}),
e_({tag: "span", clazz: `col-0-6 ve-text-center`, text: item._attunementCategory !== VeCt.STR_NO_ATTUNEMENT ? "×" : ""}),
e_({tag: "span", clazz: `col-1-4 ve-text-center`, text: (item.rarity || "").toTitleCase()}),
e_({
tag: "span",
clazz: `col-1 ve-text-center ${Parser.sourceJsonToColor(item.source)} pr-0`,
style: Parser.sourceJsonToStylePart(item.source),
title: `${Parser.sourceJsonToFull(item.source)}${Renderer.utils.getSourceSubText(item)}`,
text: source,
}),
],
}),
],
});
const listItem = new ListItem(
itI,
eleLi,
item.name,
{
source,
hash,
type,
rarity: item.rarity,
attunement: item._attunementCategory !== VeCt.STR_NO_ATTUNEMENT,
weight: Parser.weightValueToNumber(item.weight),
},
);
return {magic: listItem};
}
}
handleFilterChange () {
const f = this._pageFilter.filterBox.getValues();
const listFilter = li => this._pageFilter.toDisplay(f, this._dataList[li.ix]);
this._mundaneList.filter(listFilter);
this._magicList.filter(listFilter);
FilterBox.selectFirstVisible(this._dataList);
}
_tabTitleStats = "Item";
_renderStats_doBuildStatsTab ({ent}) {
this._$pgContent.empty().append(RenderItems.$getRenderedItem(ent));
}
async _pOnLoad_pInitPrimaryLists () {
const $iptSearch = $("#lst__search");
const $btnReset = $("#reset");
const $btnClear = $(`#lst__search-glass`);
this._mundaneList = this._initList({
$iptSearch,
$btnReset,
$btnClear,
dispPageTagline: document.getElementById(`page__subtitle`),
$wrpList: $(`.list.mundane`),
syntax: this._listSyntax.build(),
isBindFindHotkey: true,
optsList: {
fnSort: PageFilterItems.sortItems,
},
});
this._magicList = this._initList({
$iptSearch,
$btnReset,
$btnClear,
$wrpList: $(`.list.magic`),
syntax: this._listSyntax.build(),
optsList: {
fnSort: PageFilterItems.sortItems,
},
});
SortUtil.initBtnSortHandlers($("#filtertools-mundane"), this._mundaneList);
SortUtil.initBtnSortHandlers($("#filtertools-magic"), this._magicList);
this._mundaneList.nextList = this._magicList;
this._magicList.prevList = this._mundaneList;
this._filterBox = await this._pageFilter.pInitFilterBox({
$iptSearch,
$wrpFormTop: $(`#filter-search-group`),
$btnReset,
});
}
_pOnLoad_initVisibleItemsDisplay () {
const $elesMundaneAndMagic = $(`.ele-mundane-and-magic`);
$(`.side-label--mundane`).click(() => {
const filterValues = this._pageFilter.filterBox.getValues();
const curValue = MiscUtil.get(filterValues, "Miscellaneous", "Mundane");
this._pageFilter.filterBox.setFromValues({
Miscellaneous: {
...(filterValues?.Miscellaneous || {}),
Mundane: curValue === 1 ? 0 : 1,
},
});
});
$(`.side-label--magic`).click(() => {
const filterValues = this._pageFilter.filterBox.getValues();
const curValue = MiscUtil.get(filterValues, "Miscellaneous", "Magic");
this._pageFilter.filterBox.setFromValues({
Miscellaneous: {
...(filterValues?.Miscellaneous || {}),
Magic: curValue === 1 ? 0 : 1,
},
});
});
const $outVisibleResults = $(`.lst__wrp-search-visible`);
const $wrpListMundane = $(`.itm__wrp-list--mundane`);
const $wrpListMagic = $(`.itm__wrp-list--magic`);
const $elesMundane = $(`.ele-mundane`);
const $elesMagic = $(`.ele-magic`);
this._mundaneList.on("updated", () => {
// Force-show the mundane list if there are no items on display
if (this._magicList.visibleItems.length) $elesMundane.toggleVe(!!this._mundaneList.visibleItems.length);
else $elesMundane.showVe();
$elesMundaneAndMagic.toggleVe(!!(this._mundaneList.visibleItems.length && this._magicList.visibleItems.length));
const current = this._mundaneList.visibleItems.length + this._magicList.visibleItems.length;
const total = this._mundaneList.items.length + this._magicList.items.length;
$outVisibleResults.html(`${current}/${total}`);
// Collapse the mundane section if there are no magic items displayed
$wrpListMundane.toggleClass(`itm__wrp-list--empty`, this._mundaneList.visibleItems.length === 0);
});
this._magicList.on("updated", () => {
$elesMagic.toggleVe(!!this._magicList.visibleItems.length);
// Force-show the mundane list if there are no items on display
if (!this._magicList.visibleItems.length) $elesMundane.showVe();
else $elesMundane.toggleVe(!!this._mundaneList.visibleItems.length);
$elesMundaneAndMagic.toggleVe(!!(this._mundaneList.visibleItems.length && this._magicList.visibleItems.length));
const current = this._mundaneList.visibleItems.length + this._magicList.visibleItems.length;
const total = this._mundaneList.items.length + this._magicList.items.length;
$outVisibleResults.html(`${current}/${total}`);
// Collapse the magic section if there are no magic items displayed
$wrpListMagic.toggleClass(`itm__wrp-list--empty`, this._magicList.visibleItems.length === 0);
});
}
_addData (data) {
super._addData(data);
// populate table labels
$(`h3.ele-mundane span.side-label`).text("Mundane");
$(`h3.ele-magic span.side-label`).text("Magic");
}
_addListItem (listItem) {
if (listItem.mundane) this._mundaneList.addItem(listItem.mundane);
if (listItem.magic) this._magicList.addItem(listItem.magic);
}
}
const itemsPage = new ItemsPage();
itemsPage.sublistManager = new ItemsSublistManager();
window.addEventListener("load", () => itemsPage.pOnLoad());