mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
v1.208.0
This commit is contained in:
@@ -24,7 +24,7 @@ async function onJsonLoad (data) {
|
||||
|
||||
BookUtil.bookIndex = data?.adventure || [];
|
||||
|
||||
$(`.book-head-message`).text(`Select an adventure from the list on the left`);
|
||||
$(`#page__subtitle`).text(`Select an adventure from the list on the left`);
|
||||
$(`.book-loading-message`).text(`Select an adventure to begin`);
|
||||
|
||||
BookUtil.bookIndexPrerelease = (await PrereleaseUtil.pGetBrewProcessed())?.adventure || [];
|
||||
|
||||
@@ -211,13 +211,13 @@ class BestiaryPageBookView extends ListPageBookView {
|
||||
const $btnDownloadMarkdown = $(`<button class="btn btn-default btn-sm">Download as Markdown</button>`)
|
||||
.click(async () => DataUtil.userDownloadText("bestiary.md", await pGetAsMarkdown()));
|
||||
|
||||
const $btnCopyMarkdown = $(`<button class="btn btn-default btn-sm px-2" title="Copy Markdown to Clipboard"><span class="glyphicon glyphicon-copy"/></button>`)
|
||||
const $btnCopyMarkdown = $(`<button class="btn btn-default btn-sm px-2" title="Copy Markdown to Clipboard"><span class="glyphicon glyphicon-copy"></span></button>`)
|
||||
.click(async () => {
|
||||
await MiscUtil.pCopyTextToClipboard(await pGetAsMarkdown());
|
||||
JqueryUtil.showCopiedEffect($btnCopyMarkdown);
|
||||
});
|
||||
|
||||
const $btnDownloadMarkdownSettings = $(`<button class="btn btn-default btn-sm px-2" title="Markdown Settings"><span class="glyphicon glyphicon-cog"/></button>`)
|
||||
const $btnDownloadMarkdownSettings = $(`<button class="btn btn-default btn-sm px-2" title="Markdown Settings"><span class="glyphicon glyphicon-cog"></span></button>`)
|
||||
.click(async () => RendererMarkdown.pShowSettingsModal());
|
||||
|
||||
$$`<div class="ve-flex-v-center btn-group ml-2">
|
||||
@@ -306,8 +306,8 @@ class BestiaryPage extends ListPageMultiSource {
|
||||
size: {name: "Size", transform: size => Renderer.utils.getRenderedSize(size)},
|
||||
type: {name: "Type", transform: type => Parser.monTypeToFullObj(type).asText},
|
||||
alignment: {name: "Alignment", transform: align => Parser.alignmentListToFull(align)},
|
||||
ac: {name: "AC", transform: ac => Parser.acToFull(ac)},
|
||||
hp: {name: "HP", transform: hp => Renderer.monster.getRenderedHp(hp)},
|
||||
ac: {name: "AC", transform: ac => ac != null ? Parser.acToFull(ac) : ""},
|
||||
hp: {name: "HP", transform: hp => hp != null ? Renderer.monster.getRenderedHp(hp) : ""},
|
||||
_speed: {name: "Speed", transform: mon => Parser.getSpeedString(mon)},
|
||||
...Parser.ABIL_ABVS.mergeMap(ab => ({[ab]: {name: Parser.attAbvToFull(ab)}})),
|
||||
_save: {name: "Saving Throws", transform: mon => Renderer.monster.getSavesPart(mon)},
|
||||
@@ -913,14 +913,14 @@ class BestiaryPage extends ListPageMultiSource {
|
||||
};
|
||||
|
||||
// append footer first to be behind buttons
|
||||
const $footer = $(`<div class="mon__token-footer"/>`);
|
||||
const $footer = $(`<div class="mon__token-footer"></div>`);
|
||||
const $wrpFooter = $$`<div class="mon__wrp-token-footer">${$footer}</div>`.hide().appendTo($lnkToken);
|
||||
|
||||
const $btnLeft = $$`<div class="mon__btn-token-cycle mon__btn-token-cycle--left"><span class="glyphicon glyphicon-chevron-left"/></div>`
|
||||
const $btnLeft = $$`<div class="mon__btn-token-cycle mon__btn-token-cycle--left"><span class="glyphicon glyphicon-chevron-left"></span></div>`
|
||||
.click(evt => handleClick(evt, -1)).appendTo($lnkToken)
|
||||
.hide();
|
||||
|
||||
const $btnRight = $$`<div class="mon__btn-token-cycle mon__btn-token-cycle--right"><span class="glyphicon glyphicon-chevron-right"/></div>`
|
||||
const $btnRight = $$`<div class="mon__btn-token-cycle mon__btn-token-cycle--right"><span class="glyphicon glyphicon-chevron-right"></span></div>`
|
||||
.click(evt => handleClick(evt, 1)).appendTo($lnkToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ async function onJsonLoad (data) {
|
||||
|
||||
BookUtil.bookIndex = data?.book || [];
|
||||
|
||||
$(`.book-head-message`).text(`Select a book from the list on the left`);
|
||||
$(`#page__subtitle`).text(`Select a book from the list on the left`);
|
||||
$(`.book-loading-message`).text(`Select a book to begin`);
|
||||
|
||||
BookUtil.bookIndexPrerelease = (await PrereleaseUtil.pGetBrewProcessed())?.book || [];
|
||||
|
||||
@@ -260,7 +260,7 @@ class BookUtil {
|
||||
|
||||
static _showBookContent_renderNavButtons ({isTop, ixChapter, bookId, data}) {
|
||||
const tdStyle = `padding-${isTop ? "top" : "bottom"}: 6px; padding-left: 9px; padding-right: 9px;`;
|
||||
const $wrpControls = $(`<div class="split"/>`).appendTo($(`<td colspan="6" style="${tdStyle}"/>`).appendTo($(`<tr/>`).appendTo(BookUtil.$dispBook)));
|
||||
const $wrpControls = $(`<div class="split"></div>`).appendTo($(`<td colspan="6" style="${tdStyle}"></td>`).appendTo($(`<tr></tr>`).appendTo(BookUtil.$dispBook)));
|
||||
|
||||
const showPrev = ~ixChapter && ixChapter > 0;
|
||||
BookUtil.curRender.controls.$btnsPrv = BookUtil.curRender.controls.$btnsPrv || [];
|
||||
@@ -310,10 +310,10 @@ class BookUtil {
|
||||
|
||||
let $btnPrev;
|
||||
if (BookUtil.referenceId) {
|
||||
$btnPrev = $(`<button class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-left"/></button>`)
|
||||
$btnPrev = $(`<button class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-left"></span></button>`)
|
||||
.click(() => this._showBookContent_goToPage({mod: -1, bookId, ixChapter}));
|
||||
} else {
|
||||
$btnPrev = $(`<a href="#${this._showBookContent_goToPage({mod: -1, isGetHref: true, bookId, ixChapter})}" class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-left"/></a>`)
|
||||
$btnPrev = $(`<a href="#${this._showBookContent_goToPage({mod: -1, isGetHref: true, bookId, ixChapter})}" class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-left"></span></a>`)
|
||||
.click(() => MiscUtil.scrollPageTop());
|
||||
}
|
||||
$btnPrev
|
||||
@@ -324,10 +324,10 @@ class BookUtil {
|
||||
|
||||
let $btnNext;
|
||||
if (BookUtil.referenceId) {
|
||||
$btnNext = $(`<button class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-right"/></button>`)
|
||||
$btnNext = $(`<button class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-right"></span></button>`)
|
||||
.click(() => this._showBookContent_goToPage({mod: 1, bookId, ixChapter}));
|
||||
} else {
|
||||
$btnNext = $(`<a href="#${this._showBookContent_goToPage({mod: 1, isGetHref: true, bookId, ixChapter})}" class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-right"/></a>`)
|
||||
$btnNext = $(`<a href="#${this._showBookContent_goToPage({mod: 1, isGetHref: true, bookId, ixChapter})}" class="btn btn-xxs btn-default"><span class="glyphicon glyphicon-chevron-right"></span></a>`)
|
||||
.click(() => MiscUtil.scrollPageTop());
|
||||
}
|
||||
$btnNext
|
||||
@@ -359,7 +359,7 @@ class BookUtil {
|
||||
$btnToggleNarrow.toggleClass("active", this._isNarrow);
|
||||
$(`#pagecontent`).toggleClass(`bk__stats--narrow`, this._isNarrow);
|
||||
};
|
||||
const $btnToggleNarrow = $(`<button class="btn btn-xs btn-default" title="Toggle Narrow Reading Width"><span class="glyphicon glyphicon-resize-small"/></button>`)
|
||||
const $btnToggleNarrow = $(`<button class="btn btn-xs btn-default" title="Toggle Narrow Reading Width"><span class="glyphicon glyphicon-resize-small"></span></button>`)
|
||||
.click(() => {
|
||||
this._isNarrow = !this._isNarrow;
|
||||
hdlNarrowUpdate();
|
||||
@@ -399,7 +399,7 @@ class BookUtil {
|
||||
]);
|
||||
}
|
||||
|
||||
const $btnMenu = $(`<button class="btn btn-xs btn-default" title="Other Options"><span class="glyphicon glyphicon-option-vertical"/></button>`)
|
||||
const $btnMenu = $(`<button class="btn btn-xs btn-default" title="Other Options"><span class="glyphicon glyphicon-option-vertical"></span></button>`)
|
||||
.click(evt => ContextUtil.pOpenMenu(evt, this._TOP_MENU));
|
||||
|
||||
$$`<div class="no-print ve-flex-v-center btn-group">${$btnEntireBook}${$btnToggleNarrow}${$btnMenu}</div>`.appendTo($wrpControls);
|
||||
@@ -494,7 +494,7 @@ class BookUtil {
|
||||
|
||||
static initScrollTopFloat () {
|
||||
const $wrpScrollTop = Omnisearch.addScrollTopFloat();
|
||||
BookUtil.$wrpFloatControls = $(`<div class="ve-flex-vh-center w-100 mb-2 btn-group"/>`).prependTo($wrpScrollTop);
|
||||
BookUtil.$wrpFloatControls = $(`<div class="ve-flex-vh-center w-100 mb-2 btn-group"></div>`).prependTo($wrpScrollTop);
|
||||
}
|
||||
|
||||
// custom loading to serve multiple sources
|
||||
@@ -605,8 +605,8 @@ class BookUtil {
|
||||
|
||||
static async _booksHashChange_pHandleFound ({fromIndex, homebrewData, bookId, hashParts, $contents, isNewBook}) {
|
||||
document.title = `${fromIndex.name} - 5etools`;
|
||||
$(`.book-head-header`).html(this._booksHashChange_getCleanName(fromIndex));
|
||||
$(`.book-head-message`).html("Browse content. Press F to find, and G to go to page.");
|
||||
$(`#page__title`).html(this._booksHashChange_getCleanName(fromIndex));
|
||||
$(`#page__subtitle`).html("Browse content. Press F to find, and G to go to page.");
|
||||
await this._pLoadChapter(fromIndex, bookId, hashParts, homebrewData, $contents);
|
||||
NavBar.highlightCurrentPage();
|
||||
if (isNewBook) MiscUtil.scrollPageTop();
|
||||
@@ -723,7 +723,7 @@ class BookUtil {
|
||||
$(`span.temp`).contents().unwrap();
|
||||
BookUtil._lastHighlight = null;
|
||||
if (BookUtil._$findAll) BookUtil._$findAll.remove();
|
||||
BookUtil._$findAll = $(`<div class="f-all-wrapper"/>`)
|
||||
BookUtil._$findAll = $(`<div class="f-all-wrapper"></div>`)
|
||||
.on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
});
|
||||
@@ -751,8 +751,8 @@ class BookUtil {
|
||||
if (found.length) {
|
||||
$results.show();
|
||||
found.forEach(f => {
|
||||
const $row = $(`<p class="f-result"/>`);
|
||||
const $ptLink = $(`<span/>`);
|
||||
const $row = $(`<p class="f-result"></p>`);
|
||||
const $ptLink = $(`<span></span>`);
|
||||
const isLitTitle = f.headerMatches && !f.page;
|
||||
const $link = $(
|
||||
`<a href="#${BookUtil.Search.getResultHash(bookId, f)}">
|
||||
@@ -763,7 +763,7 @@ class BookUtil {
|
||||
$row.append($ptLink);
|
||||
|
||||
if (!isPageMode && f.previews) {
|
||||
const $ptPreviews = $(`<a href="#${BookUtil.Search.getResultHash(bookId, f)}"/>`);
|
||||
const $ptPreviews = $(`<a href="#${BookUtil.Search.getResultHash(bookId, f)}"></a>`);
|
||||
const re = new RegExp(f.term.escapeRegexp(), "gi");
|
||||
|
||||
$ptPreviews.on("click", evt => {
|
||||
@@ -861,7 +861,7 @@ class BookUtil {
|
||||
</a>
|
||||
<div class="ve-flex-v-center">
|
||||
<a href="${this._getHrefShowAll(book.id)}" class="bk__contents_show_all px-2 py-1p ve-flex-v-center lst__wrp-cells lst__row-inner" title="View Entire ${BookUtil.contentType.uppercaseFirst()} (Warning: Slow)">
|
||||
<span class="glyphicon glyphicon glyphicon-book" style="top: 0;"/>
|
||||
<span class="glyphicon glyphicon glyphicon-book" style="top: 0;"></span>
|
||||
</a>
|
||||
${BookUtil.curRender.$btnToggleExpandAll}
|
||||
</div>
|
||||
|
||||
@@ -4,12 +4,12 @@ window.addEventListener("load", () => {
|
||||
if (typeof [].flat !== "function") {
|
||||
const $body = $(`body`);
|
||||
$body.addClass("edge__body");
|
||||
const $btnClose = $(`<button class="btn btn-danger edge__btn-close"><span class="glyphicon glyphicon-remove"/></button>`)
|
||||
const $btnClose = $(`<button class="btn btn-danger edge__btn-close"><span class="glyphicon glyphicon-remove"></span></button>`)
|
||||
.click(() => {
|
||||
$overlay.remove();
|
||||
$body.removeClass("edge__body");
|
||||
});
|
||||
const $overlay = $(`<div class="ve-flex-col ve-flex-vh-center relative edge__overlay"/>`);
|
||||
const $overlay = $(`<div class="ve-flex-col ve-flex-vh-center relative edge__overlay"></div>`);
|
||||
$btnClose.appendTo($overlay);
|
||||
$overlay.append(`<div class="ve-flex-col ve-flex-vh-center">
|
||||
<div class="edge__title mb-2">UPDATE YOUR BROWSER</div>
|
||||
|
||||
13
js/changelog.js
Normal file
13
js/changelog.js
Normal file
@@ -0,0 +1,13 @@
|
||||
window.addEventListener("load", async () => {
|
||||
await Promise.all([
|
||||
PrereleaseUtil.pInit(),
|
||||
BrewUtil2.pInit(),
|
||||
]);
|
||||
ExcludeUtil.pInitialise().then(null); // don't await, as this is only used for search
|
||||
|
||||
DataUtil.loadJSON(`${Renderer.get().baseUrl}data/changelog.json`)
|
||||
.then(changelog => {
|
||||
const $wrp = $(`#pagecontent`).empty();
|
||||
UtilsChangelog.renderChangelog(changelog, $wrp);
|
||||
});
|
||||
});
|
||||
@@ -982,7 +982,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
<tr><th class="border" colspan="15"></th></tr>
|
||||
<tr><th class="cls-tbl__disp-name" colspan="15">${cls.name}</th></tr>
|
||||
<tr>
|
||||
<th colspan="3"/> <!-- spacer to match the 3 default cols (level, prof, features) -->
|
||||
<th colspan="3"></th> <!-- spacer to match the 3 default cols (level, prof, features) -->
|
||||
${$tblGroupHeaders}
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -1012,7 +1012,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
const $thGroupHeader = tableGroup.title
|
||||
? $(`<th class="cls-tbl__col-group" colspan="${colLabels.length}">${tableGroup.title}</th>`)
|
||||
// if there's no title, add a spacer
|
||||
: $(`<th colspan="${colLabels.length}"/>`);
|
||||
: $(`<th colspan="${colLabels.length}"></th>`);
|
||||
$tblGroupHeaders.push($thGroupHeader);
|
||||
|
||||
// Render column headers (bottom section)
|
||||
@@ -1104,7 +1104,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
hkSetHref();
|
||||
|
||||
// Make a dummy for the last item
|
||||
const $dispComma = ixFeature === lvlFeaturesFilt.length - 1 ? $(`<span/>`) : $(`<span class="mr-1">,</span>`);
|
||||
const $dispComma = ixFeature === lvlFeaturesFilt.length - 1 ? $(`<span></span>`) : $(`<span class="mr-1">,</span>`);
|
||||
return {
|
||||
$wrpLink: $$`<div class="inline-block">${$lnk}${$dispComma}</div>`,
|
||||
$dispComma,
|
||||
@@ -1331,7 +1331,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
equip.default && equip.default.length ? `<ul class="pl-4"><li>${equip.default.map(it => Renderer.get().render(it)).join("</li><li>")}</ul>` : "",
|
||||
equip.goldAlternative != null ? `<p>Alternatively, you may start with ${Renderer.get().render(equip.goldAlternative)} gp to buy your own equipment.</p>` : "",
|
||||
].filter(Boolean).join("");
|
||||
const $dispRendered = $(`<div/>`);
|
||||
const $dispRendered = $(`<div></div>`);
|
||||
|
||||
$ptEquipment = $$`<tr>
|
||||
<td class="cls-side__section" colspan="6">
|
||||
@@ -1472,7 +1472,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
// endregion
|
||||
|
||||
// region subclasses
|
||||
const $wrpScTabs = $(`<div class="ve-flex-v-center ve-flex-wrap mr-2 w-100"/>`).appendTo($wrp);
|
||||
const $wrpScTabs = $(`<div class="ve-flex-v-center ve-flex-wrap mr-2 w-100"></div>`).appendTo($wrp);
|
||||
this._listSubclass = new List({$wrpList: $wrpScTabs, isUseJquery: true, fnSort: ClassesPage._fnSortSubclassFilterItems});
|
||||
|
||||
cls.subclasses.forEach((sc, i) => {
|
||||
@@ -1481,7 +1481,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
this._listSubclass.addItem(listItem);
|
||||
});
|
||||
|
||||
const $dispCount = $(`<div class="text-muted m-1 cls-tabs__sc-not-shown ve-flex-vh-center"/>`);
|
||||
const $dispCount = $(`<div class="text-muted m-1 cls-tabs__sc-not-shown ve-flex-vh-center"></div>`);
|
||||
this._listSubclass.addItem(new ListItem(
|
||||
-1,
|
||||
$dispCount,
|
||||
@@ -1521,7 +1521,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
async _render_pInitSubclassControls ($wrp) {
|
||||
const cls = this.activeClass;
|
||||
|
||||
const $btnSelAll = $(`<button class="btn btn-xs btn-default" title="Select All (SHIFT to filter for and include most recent; CTRL to select official plus homebrew)"><span class="glyphicon glyphicon-check"/></button>`)
|
||||
const $btnSelAll = $(`<button class="btn btn-xs btn-default" title="Select All (SHIFT to filter for and include most recent; CTRL to select official plus homebrew)"><span class="glyphicon glyphicon-check"></span></button>`)
|
||||
.click(evt => {
|
||||
const allStateKeys = cls.subclasses.map(sc => UrlUtil.getStateKeySubclass(sc));
|
||||
if (evt.shiftKey) {
|
||||
@@ -1608,7 +1608,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
filterSets.forEach((it, i) => $selFilterPreset.append(`<option value="${i}">${it.name}</option>`));
|
||||
$selFilterPreset.val("-1");
|
||||
|
||||
const $btnReset = $(`<button class="btn btn-xs btn-default" title="Reset Selection"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnReset = $(`<button class="btn btn-xs btn-default" title="Reset Selection"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
this._proxyAssign("state", "_state", "__state", cls.subclasses.mergeMap(sc => ({[UrlUtil.getStateKeySubclass(sc)]: false})));
|
||||
});
|
||||
@@ -1618,9 +1618,9 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
// Remove the temporary "hidden" class used to prevent popping
|
||||
this._listSubclass.items.forEach(it => it.ele.showVe());
|
||||
|
||||
const $btnToggleSources = ComponentUiUtil.$getBtnBool(this, "isShowScSources", {$ele: $(`<button class="btn btn-xs btn-default ve-flex-1" title="Show Subclass Sources"><span class="glyphicon glyphicon-book"/></button>`)});
|
||||
const $btnToggleSources = ComponentUiUtil.$getBtnBool(this, "isShowScSources", {$ele: $(`<button class="btn btn-xs btn-default ve-flex-1" title="Show Subclass Sources"><span class="glyphicon glyphicon-book"></span></button>`)});
|
||||
|
||||
const $btnShuffle = $(`<button title="Feeling Lucky?" class="btn btn-xs btn-default ve-flex-1"><span class="glyphicon glyphicon-random"/></button>`)
|
||||
const $btnShuffle = $(`<button title="Feeling Lucky?" class="btn btn-xs btn-default ve-flex-1"><span class="glyphicon glyphicon-random"></span></button>`)
|
||||
.click(() => {
|
||||
if (!this._listSubclass.visibleItems.length) return JqueryUtil.doToast({content: "No subclasses to choose from!", type: "warning"});
|
||||
|
||||
@@ -1665,7 +1665,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
|
||||
if (this._state[stateKey] == null) this._state[stateKey] = false;
|
||||
|
||||
const $dispName = $(`<div title="${ClassesPage.getBtnTitleSubclass(sc)}"/>`);
|
||||
const $dispName = $(`<div title="${ClassesPage.getBtnTitleSubclass(sc)}"></div>`);
|
||||
const $dispSource = $(`<div class="ml-1" title="${Parser.sourceJsonToFull(sc.source)}">(${Parser.sourceJsonToAbv(sc.source)})</div>`);
|
||||
const hkSourcesVisible = () => {
|
||||
$dispName.text(this._state.isShowScSources ? ClassesPage.getBaseShortName(sc) : sc.shortName);
|
||||
@@ -1725,7 +1725,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
// Auto-hide the outline on small screens
|
||||
if (Renderer.hover.isSmallScreen()) this._state.isHideOutline = true;
|
||||
|
||||
const $dispShowHide = $(`<div class="cls-nav__disp-toggle"/>`);
|
||||
const $dispShowHide = $(`<div class="cls-nav__disp-toggle"></div>`);
|
||||
const $wrpHeadInner = $$`<div class="cls-nav__head-inner split">
|
||||
<div>Outline</div>
|
||||
${$dispShowHide}
|
||||
@@ -1736,7 +1736,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
${$wrpHeadInner}
|
||||
<hr class="cls-nav__hr">
|
||||
</div>`.appendTo(this._$wrpOutline);
|
||||
const $wrpBody = $(`<div class="nav-body"/>`).appendTo(this._$wrpOutline);
|
||||
const $wrpBody = $(`<div class="nav-body"></div>`).appendTo(this._$wrpOutline);
|
||||
|
||||
const hkShowHide = () => {
|
||||
$wrpHead.toggleClass("cls-nav__head--active", !this._state.isHideOutline);
|
||||
@@ -2108,7 +2108,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
|
||||
if (cls.otherSources) {
|
||||
const text = Renderer.utils.getSourceAndPageHtml(cls);
|
||||
const $trClassFeature = $(`<tr data-feature-type="class"><td colspan="6"/></tr>`)
|
||||
const $trClassFeature = $(`<tr data-feature-type="class"><td colspan="6"></td></tr>`)
|
||||
.fastSetHtml(`<hr class="hr-1"><b>Class source:</b> ${text}`)
|
||||
.appendTo($content);
|
||||
}
|
||||
@@ -2147,7 +2147,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
if (source === cls.source) return {isSkip: true};
|
||||
},
|
||||
fn: () => {
|
||||
return $(`<tr data-scroll-id="${ixLvl}-${ixFeature}" data-feature-type="class" class="cls-main__linked-titles"><td colspan="6"/></tr>`)
|
||||
return $(`<tr data-scroll-id="${ixLvl}-${ixFeature}" data-feature-type="class" class="cls-main__linked-titles"><td colspan="6"></td></tr>`)
|
||||
.fastSetHtml(Renderer.get().setDepthTracker(depthArr, {additionalProps: ["isReprinted"], additionalPropsInherited: ["_isStandardSource", "isClassFeatureVariant"]}).render(feature))
|
||||
.appendTo($content);
|
||||
},
|
||||
@@ -2161,7 +2161,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
|
||||
$trClassFeature.attr("data-feature-type", "gain-subclass");
|
||||
|
||||
// Add a placeholder feature to display when no subclasses are active
|
||||
const $trSubclassFeature = $(`<tr class="cls-main__sc-feature" data-subclass-none-message="true"><td colspan="6"/></tr>`)
|
||||
const $trSubclassFeature = $(`<tr class="cls-main__sc-feature" data-subclass-none-message="true"><td colspan="6"></td></tr>`)
|
||||
.fastSetHtml(Renderer.get().setDepthTracker([]).render({type: "entries", entries: [{name: `{@note No Subclass Selected}`, type: "entries", entries: [`{@note <span class="clickable roller" data-jump-select-a-subclass="true">Select a subclass</span> to view its feature(s) here.}`]}]}))
|
||||
.appendTo($content);
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class BaseConverter extends BaseComponent {
|
||||
/* -------------------------------------------- */
|
||||
|
||||
renderSidebar (parent, $parent) {
|
||||
const $wrpSidebar = $(`<div class="w-100 ve-flex-col"/>`).appendTo($parent);
|
||||
const $wrpSidebar = $(`<div class="w-100 ve-flex-col"></div>`).appendTo($parent);
|
||||
const hkShowSidebar = () => $wrpSidebar.toggleClass("hidden", parent.get("converter") !== this._converterId);
|
||||
parent.addHook("converter", hkShowSidebar);
|
||||
hkShowSidebar();
|
||||
@@ -158,7 +158,7 @@ class BaseConverter extends BaseComponent {
|
||||
_renderSidebarSourcePart (parent, $wrpSidebar) {
|
||||
if (!this._hasSource) return;
|
||||
|
||||
const $wrpSourceOverlay = $(`<div class="h-100 w-100"/>`);
|
||||
const $wrpSourceOverlay = $(`<div class="h-100 w-100"></div>`);
|
||||
let modalMeta = null;
|
||||
|
||||
const rebuildStageSource = (options) => {
|
||||
@@ -191,10 +191,10 @@ class BaseConverter extends BaseComponent {
|
||||
<select class="form-control input-xs"><option value="">(None)</option></select>`
|
||||
.change(() => this._state.source = $selSource.val());
|
||||
|
||||
$(`<option/>`, {val: "5e_divider", text: `\u2014`, disabled: true}).appendTo($selSource);
|
||||
$(`<option></option>`, {val: "5e_divider", text: `\u2014`, disabled: true}).appendTo($selSource);
|
||||
|
||||
Object.keys(Parser.SOURCE_JSON_TO_FULL)
|
||||
.forEach(src => $(`<option/>`, {val: src, text: Parser.sourceJsonToFull(src)}).appendTo($selSource));
|
||||
.forEach(src => $(`<option></option>`, {val: src, text: Parser.sourceJsonToFull(src)}).appendTo($selSource));
|
||||
|
||||
const hkAvailSources = () => {
|
||||
const curSources = new Set($selSource.find(`option`).map((i, e) => $(e).val()));
|
||||
@@ -217,7 +217,7 @@ class BaseConverter extends BaseComponent {
|
||||
const $optBrewLast = $selSource.find(`option[disabled]`).prev();
|
||||
optionsToAdd.forEach(source => {
|
||||
const fullSource = BrewUtil2.sourceJsonToSource(source);
|
||||
$(`<option/>`, {val: fullSource.json, text: fullSource.full}).insertAfter($optBrewLast);
|
||||
$(`<option></option>`, {val: fullSource.json, text: fullSource.full}).insertAfter($optBrewLast);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1367,7 +1367,7 @@ class ConverterUi extends BaseComponent {
|
||||
ConverterUiUtil.renderSideMenuDivider($mnu);
|
||||
// endregion
|
||||
|
||||
const $wrpConverters = $(`<div class="w-100 ve-flex-col"/>`).appendTo($mnu);
|
||||
const $wrpConverters = $(`<div class="w-100 ve-flex-col"></div>`).appendTo($mnu);
|
||||
Object
|
||||
.keys(this._converters)
|
||||
.sort(SortUtil.ascSortLower)
|
||||
|
||||
@@ -255,6 +255,8 @@ class AcConvert {
|
||||
case "natural & tailored leather":
|
||||
case "canny defense": // Dungeons of Drakkenheim
|
||||
return fromLow;
|
||||
|
||||
case "plate armor of bhaal": return "plate armor of Bhaal";
|
||||
// endregion
|
||||
|
||||
// region homebrew
|
||||
|
||||
@@ -57,8 +57,8 @@ function addMonsterFeatures (mfData) {
|
||||
});
|
||||
|
||||
// when clicking a row in the "Monster Statistics by Challenge Rating" table
|
||||
$("#msbcr tr").not(":has(th)").click(function () {
|
||||
if (!confirm("This will reset the calculator. Are you sure?")) return;
|
||||
$("#msbcr tr").not(":has(th)").click(async function () {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "This will reset the calculator. Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
$("#expectedcr").val($(this).children("td:eq(0)").html());
|
||||
const [minHp, maxHp] = $(this).children("td:eq(4)").html().split("-").map(it => parseInt(it));
|
||||
$("#hp").val(minHp + (maxHp - minHp) / 2);
|
||||
@@ -156,11 +156,10 @@ function addMonsterFeatures (mfData) {
|
||||
|
||||
$("#monsterfeatures .crc__wrp_mon_features input").change(calculateCr);
|
||||
|
||||
$("#crcalc_reset").click(() => {
|
||||
confirm("Are you sure?") && (() => {
|
||||
window.location = "";
|
||||
parseUrl();
|
||||
})();
|
||||
$("#crcalc_reset").click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
window.location = "";
|
||||
parseUrl();
|
||||
});
|
||||
|
||||
parseUrl();
|
||||
|
||||
186
js/dmscreen.js
186
js/dmscreen.js
@@ -768,12 +768,16 @@ class SideMenu {
|
||||
const $wrpResizeH = $(`<div class="w-100 mb-2 split-v-center"><div class="sidemenu__row__label">Height</div></div>`).appendTo(this.$mnu);
|
||||
const $iptHeight = $(`<input class="form-control" type="number" value="${this.board.height}">`).appendTo($wrpResizeH);
|
||||
this.$iptHeight = $iptHeight;
|
||||
const $wrpSetDim = $(`<div class="w-100 split-v-center"/>`).appendTo(this.$mnu);
|
||||
const $wrpSetDim = $(`<div class="w-100 split-v-center"></div>`).appendTo(this.$mnu);
|
||||
const $btnSetDim = $(`<button class="btn btn-primary" style="width: 100%;">Set Dimensions</div>`).appendTo($wrpSetDim);
|
||||
$btnSetDim.on("click", () => {
|
||||
$btnSetDim.on("click", async () => {
|
||||
const w = Number($iptWidth.val());
|
||||
const h = Number($iptHeight.val());
|
||||
if ((w > 10 || h > 10) && !window.confirm("That's a lot of panels. You sure?")) return;
|
||||
|
||||
if (w > 10 || h > 10) {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Too Many Panels", htmlDescription: "That's a lot of panels. Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
}
|
||||
|
||||
this.board.setDimensions(w, h);
|
||||
});
|
||||
renderDivider();
|
||||
@@ -782,7 +786,7 @@ class SideMenu {
|
||||
const $btnFullscreen = $(`<button class="btn btn-primary">Toggle Fullscreen</button>`).appendTo($wrpFullscreen);
|
||||
this.board.$btnFullscreen = $btnFullscreen;
|
||||
$btnFullscreen.on("click", () => this.board.doToggleFullscreen());
|
||||
const $btnLockPanels = $(`<button class="btn btn-danger" title="Lock Panels"><span class="glyphicon glyphicon-lock"/></button>`).appendTo($wrpFullscreen);
|
||||
const $btnLockPanels = $(`<button class="btn btn-danger" title="Lock Panels"><span class="glyphicon glyphicon-lock"></span></button>`).appendTo($wrpFullscreen);
|
||||
this.board.$btnLockPanels = $btnLockPanels;
|
||||
$btnLockPanels.on("click", () => {
|
||||
this.board.isLocked = !this.board.isLocked;
|
||||
@@ -798,8 +802,8 @@ class SideMenu {
|
||||
});
|
||||
renderDivider();
|
||||
|
||||
const $wrpSaveLoad = $(`<div class="w-100"/>`).appendTo(this.$mnu);
|
||||
const $wrpSaveLoadFile = $(`<div class="w-100 mb-2 ve-flex-vh-center-around"/>`).appendTo($wrpSaveLoad);
|
||||
const $wrpSaveLoad = $(`<div class="w-100"></div>`).appendTo(this.$mnu);
|
||||
const $wrpSaveLoadFile = $(`<div class="w-100 mb-2 ve-flex-vh-center-around"></div>`).appendTo($wrpSaveLoad);
|
||||
const $btnSaveFile = $(`<button class="btn btn-primary">Save to File</button>`).appendTo($wrpSaveLoadFile);
|
||||
$btnSaveFile.on("click", () => {
|
||||
DataUtil.userDownload(`dm-screen`, this.board.getSaveableState(), {fileType: "dm-screen"});
|
||||
@@ -814,7 +818,7 @@ class SideMenu {
|
||||
this.board.doReset();
|
||||
await this.board.pDoLoadStateFrom(jsons[0]);
|
||||
});
|
||||
const $wrpSaveLoadUrl = $(`<div class="w-100 ve-flex-vh-center-around"/>`).appendTo($wrpSaveLoad);
|
||||
const $wrpSaveLoadUrl = $(`<div class="w-100 ve-flex-vh-center-around"></div>`).appendTo($wrpSaveLoad);
|
||||
const $btnSaveLink = $(`<button class="btn btn-primary">Save to URL</button>`).appendTo($wrpSaveLoadUrl);
|
||||
$btnSaveLink.on("click", async () => {
|
||||
const encoded = `${window.location.href.split("#")[0]}#${encodeURIComponent(JSON.stringify(this.board.getSaveableState()))}`;
|
||||
@@ -827,16 +831,15 @@ class SideMenu {
|
||||
this.board.$cbConfirmTabClose = $(`<input type="checkbox" class="sidemenu__row__label__cb">`).appendTo($wrpCbConfirm.find(`label`));
|
||||
renderDivider();
|
||||
|
||||
const $wrpReset = $(`<div class="w-100 split-v-center"/>`).appendTo(this.$mnu);
|
||||
const $wrpReset = $(`<div class="w-100 split-v-center"></div>`).appendTo(this.$mnu);
|
||||
const $btnReset = $(`<button class="btn btn-danger" style="width: 100%;">Reset Screen</button>`).appendTo($wrpReset);
|
||||
$btnReset.on("click", () => {
|
||||
if (window.confirm("Are you sure?")) {
|
||||
this.board.doReset();
|
||||
}
|
||||
$btnReset.on("click", async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
this.board.doReset();
|
||||
});
|
||||
renderDivider();
|
||||
|
||||
this.$wrpHistory = $(`<div class="sidemenu__history"/>`).appendTo(this.$mnu);
|
||||
this.$wrpHistory = $(`<div class="sidemenu__history"></div>`).appendTo(this.$mnu);
|
||||
}
|
||||
|
||||
doUpdateDimensions () {
|
||||
@@ -857,10 +860,10 @@ class SideMenu {
|
||||
});
|
||||
}
|
||||
this.board.exiledPanels.forEach((p, i) => {
|
||||
const $wrpHistItem = $(`<div class="sidemenu__history-item"/>`).appendTo(this.$wrpHistory);
|
||||
const $cvrHistItem = $(`<div class="sidemenu__history-item-cover"/>`).appendTo($wrpHistItem);
|
||||
const $btnRemove = $(`<div class="panel-history-control-remove-wrapper"><span class="panel-history-control-remove glyphicon glyphicon-remove" title="Remove"/></div>`).appendTo($cvrHistItem);
|
||||
const $ctrlMove = $(`<div class="panel-history-control-middle" title="Move"/>`).appendTo($cvrHistItem);
|
||||
const $wrpHistItem = $(`<div class="sidemenu__history-item"></div>`).appendTo(this.$wrpHistory);
|
||||
const $cvrHistItem = $(`<div class="sidemenu__history-item-cover"></div>`).appendTo($wrpHistItem);
|
||||
const $btnRemove = $(`<div class="panel-history-control-remove-wrapper"><span class="panel-history-control-remove glyphicon glyphicon-remove" title="Remove"></span></div>`).appendTo($cvrHistItem);
|
||||
const $ctrlMove = $(`<div class="panel-history-control-middle" title="Move"></div>`).appendTo($cvrHistItem);
|
||||
|
||||
$btnRemove.on("click", () => {
|
||||
this.board.exiledPanels[i].destroy();
|
||||
@@ -1205,8 +1208,8 @@ class Panel {
|
||||
|
||||
const fn = Renderer.hover.getFnRenderCompact(page);
|
||||
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"/>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"/>`).appendTo($contentInner);
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"></div>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"></table>`).appendTo($contentInner);
|
||||
$contentStats.append(fn(it));
|
||||
|
||||
const fnBind = Renderer.hover.getFnBindListenersCompact(page);
|
||||
@@ -1397,8 +1400,8 @@ class Panel {
|
||||
hash,
|
||||
).then(it => {
|
||||
ScaleCreature.scale(it, targetCr).then(initialRender => {
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"/>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"/>`).appendTo($contentInner);
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"></div>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"></table>`).appendTo($contentInner);
|
||||
$contentStats.append(Renderer.monster.getCompactRenderedString(initialRender, {isShowScalers: true, isScaledCr: true}));
|
||||
|
||||
this._stats_bindCrScaleClickHandler(it, meta, $contentInner, $contentStats);
|
||||
@@ -1428,8 +1431,8 @@ class Panel {
|
||||
hash,
|
||||
).then(it => {
|
||||
ScaleSpellSummonedCreature.scale(it, summonSpellLevel).then(scaledMon => {
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"/>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"/>`).appendTo($contentInner);
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"></div>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"></table>`).appendTo($contentInner);
|
||||
$contentStats.append(Renderer.monster.getCompactRenderedString(scaledMon, {isShowScalers: true, isScaledSpellSummon: true}));
|
||||
|
||||
this._stats_doUpdateSummonScaleDropdowns(scaledMon, $contentStats);
|
||||
@@ -1461,8 +1464,8 @@ class Panel {
|
||||
hash,
|
||||
).then(it => {
|
||||
ScaleClassSummonedCreature.scale(it, summonClassLevel).then(scaledMon => {
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"/>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"/>`).appendTo($contentInner);
|
||||
const $contentInner = $(`<div class="panel-content-wrapper-inner"></div>`);
|
||||
const $contentStats = $(`<table class="w-100 stats"></table>`).appendTo($contentInner);
|
||||
$contentStats.append(Renderer.monster.getCompactRenderedString(scaledMon, {isShowScalers: true, isScaledClassSummon: true}));
|
||||
|
||||
this._stats_doUpdateSummonScaleDropdowns(scaledMon, $contentStats);
|
||||
@@ -1554,7 +1557,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_ROLLBOX,
|
||||
null,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(Renderer.dice.get$Roller().addClass("rollbox-panel")),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(Renderer.dice.get$Roller().addClass("rollbox-panel")),
|
||||
title || "Dice Roller",
|
||||
true,
|
||||
!!title,
|
||||
@@ -1565,7 +1568,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_COUNTER,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(Counter.$getCounter(this.board, state)),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(Counter.$getCounter(this.board, state)),
|
||||
title || "Counter",
|
||||
true,
|
||||
);
|
||||
@@ -1575,7 +1578,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_UNIT_CONVERTER,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(UnitConverter.make$Converter(this.board, state)),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(UnitConverter.make$Converter(this.board, state)),
|
||||
title || "Unit Converter",
|
||||
true,
|
||||
);
|
||||
@@ -1585,7 +1588,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_MONEY_CONVERTER,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(MoneyConverter.make$Converter(this.board, state)),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(MoneyConverter.make$Converter(this.board, state)),
|
||||
title || "Money Converter",
|
||||
true,
|
||||
);
|
||||
@@ -1595,7 +1598,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_TIME_TRACKER,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(TimeTracker.$getTracker(this.board, state)),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(TimeTracker.$getTracker(this.board, state)),
|
||||
title || "Time Tracker",
|
||||
true,
|
||||
);
|
||||
@@ -1605,7 +1608,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_TEXTBOX,
|
||||
null,
|
||||
$(`<div class="panel-content-wrapper-inner ve-overflow-y-hidden"/>`).append(NoteBox.make$Notebox(this.board, content)),
|
||||
$(`<div class="panel-content-wrapper-inner ve-overflow-y-hidden"></div>`).append(NoteBox.make$Notebox(this.board, content)),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -1639,7 +1642,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_TWITCH_CHAT,
|
||||
meta,
|
||||
$(`<div class="panel-content-wrapper-inner"><iframe src="${url}?parent=${location.hostname}" frameborder="0" scrolling="no" id="${channelId}"/></div>`),
|
||||
$(`<div class="panel-content-wrapper-inner"><iframe src="${url}?parent=${location.hostname}" frameborder="0" scrolling="no" id="${channelId}"></iframe></div>`),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -1650,7 +1653,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_GENERIC_EMBED,
|
||||
meta,
|
||||
$(`<div class="panel-content-wrapper-inner"><iframe src="${url}"/></div>`),
|
||||
$(`<div class="panel-content-wrapper-inner"><iframe src="${url}"></iframe></div>`),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -1658,10 +1661,10 @@ class Panel {
|
||||
|
||||
doPopulate_Image (url, title = "Image") {
|
||||
const meta = {u: url};
|
||||
const $wrpPanel = $(`<div class="panel-content-wrapper-inner"/>`);
|
||||
const $wrpImage = $(`<div class="panel-content-wrapper-img"/>`).appendTo($wrpPanel);
|
||||
const $wrpPanel = $(`<div class="panel-content-wrapper-inner"></div>`);
|
||||
const $wrpImage = $(`<div class="panel-content-wrapper-img"></div>`).appendTo($wrpPanel);
|
||||
const $img = $(`<img src="${url}" alt="${title}" loading="lazy">`).appendTo($wrpImage);
|
||||
const $iptReset = $(`<button class="panel-zoom-reset btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"/></button>`).appendTo($wrpPanel);
|
||||
const $iptReset = $(`<button class="panel-zoom-reset btn btn-xs btn-default"><span class="glyphicon glyphicon-refresh"></span></button>`).appendTo($wrpPanel);
|
||||
const $iptRange = $(`<input type="range" class="panel-zoom-slider">`).appendTo($wrpPanel);
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_IMAGE,
|
||||
@@ -1683,7 +1686,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_ADVENTURE_DYNAMIC_MAP,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(DmMapper.$getMapper(this.board, state)),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(DmMapper.$getMapper(this.board, state)),
|
||||
title || "Map Viewer",
|
||||
true,
|
||||
);
|
||||
@@ -1693,7 +1696,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_ERROR,
|
||||
state,
|
||||
$(`<div class="panel-content-wrapper-inner"/>`).append(`<div class="w-100 h-100 ve-flex-vh-center text-danger"><div>${state.message}</div></div>`),
|
||||
$(`<div class="panel-content-wrapper-inner"></div>`).append(`<div class="w-100 h-100 ve-flex-vh-center text-danger"><div>${state.message}</div></div>`),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -1704,7 +1707,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_BLANK,
|
||||
meta,
|
||||
$(`<div class="dm-blank__panel"/>`),
|
||||
$(`<div class="dm-blank__panel"></div>`),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -2094,22 +2097,22 @@ class Panel {
|
||||
};
|
||||
|
||||
function doInitialRender () {
|
||||
const $pnl = $(`<div data-panelId="${this.id}" class="dm-screen-panel min-w-0 min-h-0" empty="true"/>`);
|
||||
const $pnl = $(`<div data-panelId="${this.id}" class="dm-screen-panel min-w-0 min-h-0" empty="true"></div>`);
|
||||
this.$pnl = $pnl;
|
||||
const $ctrlBar = $(`<div class="panel-control-bar"/>`).appendTo($pnl);
|
||||
this.$pnlTitle = $(`<div class="panel-control-bar panel-control-title"/>`).appendTo($pnl).click(() => this.$pnlTitle.toggleClass("panel-control-title--bumped"));
|
||||
this.$pnlAddTab = $(`<div class="panel-control-bar panel-control-addtab"><div class="panel-control-icon glyphicon glyphicon-plus" title="Add Tab"/></div>`).click(() => {
|
||||
const $ctrlBar = $(`<div class="panel-control-bar"></div>`).appendTo($pnl);
|
||||
this.$pnlTitle = $(`<div class="panel-control-bar panel-control-title"></div>`).appendTo($pnl).click(() => this.$pnlTitle.toggleClass("panel-control-title--bumped"));
|
||||
this.$pnlAddTab = $(`<div class="panel-control-bar panel-control-addtab"><div class="panel-control-icon glyphicon glyphicon-plus" title="Add Tab"></div></div>`).click(() => {
|
||||
this.setIsTabs(true);
|
||||
this.setDirty(true);
|
||||
this.render();
|
||||
openAddMenu();
|
||||
}).appendTo($pnl);
|
||||
|
||||
const $ctrlMove = $(`<div class="panel-control-icon glyphicon glyphicon-move" title="Move"/>`).appendTo($ctrlBar);
|
||||
const $ctrlMove = $(`<div class="panel-control-icon glyphicon glyphicon-move" title="Move"></div>`).appendTo($ctrlBar);
|
||||
$ctrlMove.on("click", () => {
|
||||
this.toggleMovable();
|
||||
});
|
||||
const $ctrlEmpty = $(`<div class="panel-control-icon glyphicon glyphicon-remove" title="Close"/>`).appendTo($ctrlBar);
|
||||
const $ctrlEmpty = $(`<div class="panel-control-icon glyphicon glyphicon-remove" title="Close"></div>`).appendTo($ctrlBar);
|
||||
$ctrlEmpty.on("click", () => {
|
||||
this.getReplacementPanel();
|
||||
});
|
||||
@@ -2118,9 +2121,9 @@ class Panel {
|
||||
this.joyMenu = joyMenu;
|
||||
joyMenu.initialise();
|
||||
|
||||
const $wrpContent = $(`<div class="panel-content-wrapper"/>`).appendTo($pnl);
|
||||
const $wrpBtnAdd = $(`<div class="panel-add"/>`).appendTo($wrpContent);
|
||||
const $btnAdd = $(`<span class="btn-panel-add glyphicon glyphicon-plus"/>`)
|
||||
const $wrpContent = $(`<div class="panel-content-wrapper"></div>`).appendTo($pnl);
|
||||
const $wrpBtnAdd = $(`<div class="panel-add"></div>`).appendTo($wrpContent);
|
||||
const $btnAdd = $(`<span class="btn-panel-add glyphicon glyphicon-plus"></span>`)
|
||||
.on("click", () => {
|
||||
openAddMenu();
|
||||
})
|
||||
@@ -2144,13 +2147,13 @@ class Panel {
|
||||
this.$btnAddInner = $btnAdd;
|
||||
this.$pnlWrpContent = $wrpContent;
|
||||
|
||||
const $wrpTabs = $(`<div class="content-tab-bar ve-flex"/>`).hideVe().appendTo($pnl);
|
||||
const $wrpTabsInner = $(`<div class="content-tab-bar-inner"/>`).on("wheel", (evt) => {
|
||||
const $wrpTabs = $(`<div class="content-tab-bar ve-flex"></div>`).hideVe().appendTo($pnl);
|
||||
const $wrpTabsInner = $(`<div class="content-tab-bar-inner"></div>`).on("wheel", (evt) => {
|
||||
const delta = evt.originalEvent.deltaY;
|
||||
const curr = $wrpTabsInner.scrollLeft();
|
||||
$wrpTabsInner.scrollLeft(Math.max(0, curr + delta));
|
||||
}).appendTo($wrpTabs);
|
||||
const $btnTabAdd = $(`<button class="btn btn-default content-tab"><span class="glyphicon glyphicon-plus"/></button>`)
|
||||
const $btnTabAdd = $(`<button class="btn btn-default content-tab"><span class="glyphicon glyphicon-plus"></span></button>`)
|
||||
.click(() => openAddMenu()).appendTo($wrpTabsInner);
|
||||
this.$pnlWrpTabs = $wrpTabs;
|
||||
this.$pnlTabs = $wrpTabsInner;
|
||||
@@ -2280,8 +2283,11 @@ class Panel {
|
||||
_get$BtnSelTab (ix, title, tabCanRename) {
|
||||
title = title || "[Untitled]";
|
||||
|
||||
const doCloseTabWithConfirmation = () => {
|
||||
if (!this.board.getConfirmTabClose() || (this.board.getConfirmTabClose() && confirm(`Are you sure you want to close tab "${this.tabDatas[ix].title}"?`))) this.doCloseTab(ix);
|
||||
const doCloseTabWithConfirmation = async () => {
|
||||
if (this.board.getConfirmTabClose()) {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Close Tab", htmlDescription: `Are you sure you want to close tab "${this.tabDatas[ix].title}"?`, textYes: "Yes", textNo: "Cancel"})) return;
|
||||
}
|
||||
this.doCloseTab(ix);
|
||||
};
|
||||
|
||||
const $btnSelTab = $(`<span class="btn btn-default content-tab ve-flex ${tabCanRename ? "content-tab-can-rename" : ""}"><span class="content-tab-title ve-overflow-ellipsis" title="${title}">${title}</span></span>`)
|
||||
@@ -2303,7 +2309,7 @@ class Panel {
|
||||
}
|
||||
}
|
||||
});
|
||||
const $btnCloseTab = $(`<span class="glyphicon glyphicon-remove content-tab-remove"/>`)
|
||||
const $btnCloseTab = $(`<span class="glyphicon glyphicon-remove content-tab-remove"></span>`)
|
||||
.on("mousedown", (evt) => {
|
||||
if (evt.button === 0) {
|
||||
evt.stopPropagation();
|
||||
@@ -2986,13 +2992,13 @@ class AddMenu {
|
||||
render () {
|
||||
if (!this._$menuInner) {
|
||||
this._$menuInner = $(`<div class="ve-flex-col w-100 h-100">`);
|
||||
const $tabBar = $(`<div class="panel-addmenu-bar"/>`).appendTo(this._$menuInner);
|
||||
this.$tabView = $(`<div class="panel-addmenu-view"/>`).appendTo(this._$menuInner);
|
||||
const $tabBar = $(`<div class="panel-addmenu-bar"></div>`).appendTo(this._$menuInner);
|
||||
this.$tabView = $(`<div class="panel-addmenu-view"></div>`).appendTo(this._$menuInner);
|
||||
|
||||
this.tabs.forEach(t => {
|
||||
t.render();
|
||||
const $head = $(`<button class="btn btn-default panel-addmenu-tab-head">${t.label}</button>`).appendTo($tabBar);
|
||||
const $body = $(`<div class="panel-addmenu-tab-body"/>`).appendTo($tabBar);
|
||||
const $body = $(`<div class="panel-addmenu-tab-body"></div>`).appendTo($tabBar);
|
||||
$body.append(t.get$Tab);
|
||||
t.$head = $head;
|
||||
t.$body = $body;
|
||||
@@ -3056,9 +3062,9 @@ class AddMenuVideoTab extends AddMenuTab {
|
||||
|
||||
render () {
|
||||
if (!this.$tab) {
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs" id="${this.tabId}"/>`);
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs" id="${this.tabId}"></div>`);
|
||||
|
||||
const $wrpYT = $(`<div class="ui-modal__row"/>`).appendTo($tab);
|
||||
const $wrpYT = $(`<div class="ui-modal__row"></div>`).appendTo($tab);
|
||||
const $iptUrlYT = $(`<input class="form-control" placeholder="Paste YouTube URL">`)
|
||||
.on("keydown", (e) => {
|
||||
if (e.which === 13) $btnAddYT.click();
|
||||
@@ -3081,7 +3087,7 @@ class AddMenuVideoTab extends AddMenuTab {
|
||||
}
|
||||
});
|
||||
|
||||
const $wrpTwitch = $(`<div class="ui-modal__row"/>`).appendTo($tab);
|
||||
const $wrpTwitch = $(`<div class="ui-modal__row"></div>`).appendTo($tab);
|
||||
const $iptUrlTwitch = $(`<input class="form-control" placeholder="Paste Twitch URL">`)
|
||||
.on("keydown", (e) => {
|
||||
if (e.which === 13) $btnAddTwitch.click();
|
||||
@@ -3124,7 +3130,7 @@ class AddMenuVideoTab extends AddMenuTab {
|
||||
}
|
||||
});
|
||||
|
||||
const $wrpGeneric = $(`<div class="ui-modal__row"/>`).appendTo($tab);
|
||||
const $wrpGeneric = $(`<div class="ui-modal__row"></div>`).appendTo($tab);
|
||||
const $iptUrlGeneric = $(`<input class="form-control" placeholder="Paste any URL">`)
|
||||
.on("keydown", (e) => {
|
||||
if (e.which === 13) $iptUrlGeneric.click();
|
||||
@@ -3157,10 +3163,10 @@ class AddMenuImageTab extends AddMenuTab {
|
||||
|
||||
render () {
|
||||
if (!this.$tab) {
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs" id="${this.tabId}"/>`);
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs" id="${this.tabId}"></div>`);
|
||||
|
||||
// region Imgur
|
||||
const $wrpImgur = $(`<div class="ui-modal__row"/>`).appendTo($tab);
|
||||
const $wrpImgur = $(`<div class="ui-modal__row"></div>`).appendTo($tab);
|
||||
$(`<span>Imgur (Anonymous Upload) <i class="text-muted">(accepts <a href="https://help.imgur.com/hc/articles/115000083326" target="_blank" rel="noopener noreferrer">imgur-friendly formats</a>)</i></span>`).appendTo($wrpImgur);
|
||||
const $iptFile = $(`<input type="file" class="hidden">`).on("change", (evt) => {
|
||||
const input = evt.target;
|
||||
@@ -3213,7 +3219,7 @@ class AddMenuImageTab extends AddMenuTab {
|
||||
// endregion
|
||||
|
||||
// region URL
|
||||
const $wrpUtl = $(`<div class="ui-modal__row"/>`).appendTo($tab);
|
||||
const $wrpUtl = $(`<div class="ui-modal__row"></div>`).appendTo($tab);
|
||||
const $iptUrl = $(`<input class="form-control" placeholder="Paste image URL">`)
|
||||
.on("keydown", (e) => {
|
||||
if (e.which === 13) $btnAddUrl.click();
|
||||
@@ -3234,7 +3240,7 @@ class AddMenuImageTab extends AddMenuTab {
|
||||
});
|
||||
// endregion
|
||||
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
// region Adventure dynamic viewer
|
||||
const $btnSelectAdventure = $(`<button class="btn btn-primary btn-sm">Add</button>`)
|
||||
@@ -3259,7 +3265,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
|
||||
render () {
|
||||
if (!this.$tab) {
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs ve-overflow-y-auto pr-1" id="${this.tabId}"/>`);
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs ve-overflow-y-auto pr-1" id="${this.tabId}"></div>`);
|
||||
|
||||
const $wrpRoller = $(`<div class="ui-modal__row"><span>Dice Roller <i class="text-muted">(pins the existing dice roller to a panel)</i></span></div>`).appendTo($tab);
|
||||
const $btnRoller = $(`<button class="btn btn-primary btn-sm">Pin</button>`).appendTo($wrpRoller);
|
||||
@@ -3267,7 +3273,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
Renderer.dice.bindDmScreenPanel(this.menu.pnl);
|
||||
this.menu.doClose();
|
||||
});
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $btnTracker = $(`<button class="btn btn-primary btn-sm">Add</button>`)
|
||||
.on("click", async () => {
|
||||
@@ -3317,7 +3323,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
${$btnPlayerTrackerV0}
|
||||
</div>`.appendTo($tab);
|
||||
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $btnSublist = $(`<button class="btn btn-primary btn-sm">Add</button>`)
|
||||
.click(async evt => {
|
||||
@@ -3330,7 +3336,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
${$btnSublist}
|
||||
</div>`.appendTo($tab);
|
||||
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $btnSwitchToEmbedTag = $(`<button class="btn btn-default btn-xxs">embed</button>`)
|
||||
.click(() => {
|
||||
@@ -3343,7 +3349,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
this.menu.pnl.doPopulate_TextBox();
|
||||
this.menu.doClose();
|
||||
});
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $wrpUnitConverter = $(`<div class="ui-modal__row"><span>Unit Converter</span></div>`).appendTo($tab);
|
||||
const $btnUnitConverter = $(`<button class="btn btn-primary btn-sm">Add</button>`).appendTo($wrpUnitConverter);
|
||||
@@ -3366,7 +3372,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
this.menu.doClose();
|
||||
});
|
||||
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $wrpTimeTracker = $(`<div class="ui-modal__row"><span>In-Game Clock/Calendar</span></div>`).appendTo($tab);
|
||||
const $btnTimeTracker = $(`<button class="btn btn-primary btn-sm">Add</button>`).appendTo($wrpTimeTracker);
|
||||
@@ -3375,7 +3381,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
this.menu.doClose();
|
||||
});
|
||||
|
||||
$(`<hr class="hr-2"/>`).appendTo($tab);
|
||||
$(`<hr class="hr-2">`).appendTo($tab);
|
||||
|
||||
const $wrpBlank = $(`<div class="ui-modal__row"><span class="help" title="For those who don't like plus signs.">Blank Space</span></div>`).appendTo($tab);
|
||||
$(`<button class="btn btn-primary btn-sm">Add</button>`)
|
||||
@@ -3589,8 +3595,8 @@ class AddMenuSearchTab extends AddMenuTab {
|
||||
};
|
||||
|
||||
if (!this.$tab) {
|
||||
const $tab = $(`<div class="ui-search__wrp-output" id="${this.tabId}"/>`);
|
||||
const $wrpCtrls = $(`<div class="ui-search__wrp-controls ui-search__wrp-controls--in-tabs"/>`).appendTo($tab);
|
||||
const $tab = $(`<div class="ui-search__wrp-output" id="${this.tabId}"></div>`);
|
||||
const $wrpCtrls = $(`<div class="ui-search__wrp-controls ui-search__wrp-controls--in-tabs"></div>`).appendTo($tab);
|
||||
|
||||
const $selCat = $(`
|
||||
<select class="form-control ui-search__sel-category">
|
||||
@@ -3606,7 +3612,7 @@ class AddMenuSearchTab extends AddMenuTab {
|
||||
});
|
||||
|
||||
const $srch = $(`<input class="ui-search__ipt-search search form-control" autocomplete="off" placeholder="Search...">`).blurOnEsc().appendTo($wrpCtrls);
|
||||
const $results = $(`<div class="ui-search__wrp-results"/>`).appendTo($tab);
|
||||
const $results = $(`<div class="ui-search__wrp-results"></div>`).appendTo($tab);
|
||||
|
||||
SearchWidget.bindAutoSearch($srch, {
|
||||
flags,
|
||||
@@ -3856,12 +3862,12 @@ class UnitConverter {
|
||||
let ixConv = state.c || 0;
|
||||
let dirConv = state.d || 0;
|
||||
|
||||
const $wrpConverter = $(`<div class="dm-unitconv dm__panel-bg split-column"/>`);
|
||||
const $wrpConverter = $(`<div class="dm-unitconv dm__panel-bg split-column"></div>`);
|
||||
|
||||
const $tblConvert = $(`<table class="w-100 table-striped"/>`).appendTo($wrpConverter);
|
||||
const $tbodyConvert = $(`<tbody/>`).appendTo($tblConvert);
|
||||
const $tblConvert = $(`<table class="w-100 table-striped"></table>`).appendTo($wrpConverter);
|
||||
const $tbodyConvert = $(`<tbody></tbody>`).appendTo($tblConvert);
|
||||
units.forEach((u, i) => {
|
||||
const $tr = $(`<tr class="row clickable"/>`).appendTo($tbodyConvert);
|
||||
const $tr = $(`<tr class="row clickable"></tr>`).appendTo($tbodyConvert);
|
||||
const clickL = () => {
|
||||
ixConv = i;
|
||||
dirConv = 0;
|
||||
@@ -3878,10 +3884,10 @@ class UnitConverter {
|
||||
$(`<td class="ve-col-3 code">×${u.x2.padStart(5)}</td>`).click(clickR).appendTo($tr);
|
||||
});
|
||||
|
||||
const $wrpIpt = $(`<div class="split dm-unitconv__wrp-ipt"/>`).appendTo($wrpConverter);
|
||||
const $wrpIpt = $(`<div class="split dm-unitconv__wrp-ipt"></div>`).appendTo($wrpConverter);
|
||||
|
||||
const $wrpLeft = $(`<div class="split-column dm-unitconv__wrp-ipt-inner"/>`).appendTo($wrpIpt);
|
||||
const $lblLeft = $(`<span class="bold"/>`).appendTo($wrpLeft);
|
||||
const $wrpLeft = $(`<div class="split-column dm-unitconv__wrp-ipt-inner"></div>`).appendTo($wrpIpt);
|
||||
const $lblLeft = $(`<span class="bold"></span>`).appendTo($wrpLeft);
|
||||
const $iptLeft = $(`<textarea class="dm-unitconv__ipt form-control">${state.i || ""}</textarea>`).appendTo($wrpLeft);
|
||||
|
||||
const $btnSwitch = $(`<button class="btn btn-primary dm-unitconv__btn-switch">⇆</button>`).click(() => {
|
||||
@@ -3889,9 +3895,9 @@ class UnitConverter {
|
||||
updateDisplay();
|
||||
}).appendTo($wrpIpt);
|
||||
|
||||
const $wrpRight = $(`<div class="split-column dm-unitconv__wrp-ipt-inner"/>`).appendTo($wrpIpt);
|
||||
const $lblRight = $(`<span class="bold"/>`).appendTo($wrpRight);
|
||||
const $iptRight = $(`<textarea class="dm-unitconv__ipt form-control" disabled style="background: #0000"/>`).appendTo($wrpRight);
|
||||
const $wrpRight = $(`<div class="split-column dm-unitconv__wrp-ipt-inner"></div>`).appendTo($wrpIpt);
|
||||
const $lblRight = $(`<span class="bold"></span>`).appendTo($wrpRight);
|
||||
const $iptRight = $(`<textarea class="dm-unitconv__ipt form-control" disabled style="background: #0000"></textarea>`).appendTo($wrpRight);
|
||||
|
||||
const updateDisplay = () => {
|
||||
const it = units[ixConv];
|
||||
@@ -3972,15 +3978,15 @@ class AdventureOrBookView {
|
||||
}
|
||||
|
||||
$getEle () {
|
||||
this._$titlePrev = $(`<div class="dm-book__controls-title ve-overflow-ellipsis text-right"/>`);
|
||||
this._$titleNext = $(`<div class="dm-book__controls-title ve-overflow-ellipsis"/>`);
|
||||
this._$titlePrev = $(`<div class="dm-book__controls-title ve-overflow-ellipsis text-right"></div>`);
|
||||
this._$titleNext = $(`<div class="dm-book__controls-title ve-overflow-ellipsis"></div>`);
|
||||
|
||||
const $btnPrev = $(`<button class="btn btn-xs btn-default mr-2" title="Previous Chapter"><span class="glyphicon glyphicon-chevron-left"/></button>`)
|
||||
const $btnPrev = $(`<button class="btn btn-xs btn-default mr-2" title="Previous Chapter"><span class="glyphicon glyphicon-chevron-left"></span></button>`)
|
||||
.click(() => this._handleButtonClick(-1));
|
||||
const $btnNext = $(`<button class="btn btn-xs btn-default" title="Next Chapter"><span class="glyphicon glyphicon-chevron-right"/></button>`)
|
||||
const $btnNext = $(`<button class="btn btn-xs btn-default" title="Next Chapter"><span class="glyphicon glyphicon-chevron-right"></span></button>`)
|
||||
.click(() => this._handleButtonClick(1));
|
||||
|
||||
this._$wrpContent = $(`<div class="h-100"/>`);
|
||||
this._$wrpContent = $(`<div class="h-100"></div>`);
|
||||
this._$wrpContentOuter = $$`<div class="h-100 dm-book__wrp-content">
|
||||
<table class="w-100 stats stats--book stats--book-hover"><tr class="text"><td colspan="6">${this._$wrpContent}</td></tr></table>
|
||||
</div>`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export class Counter {
|
||||
static $getCounter (board, state) {
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-cnt__root dm__panel-bg dm__data-anchor"/>`) // root class used to identify for saving
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-cnt__root dm__panel-bg dm__data-anchor"></div>`) // root class used to identify for saving
|
||||
.data("getState", () => counters.getSaveableState());
|
||||
const counters = new CounterRoot(board, $wrpPanel);
|
||||
counters.setStateFrom(state);
|
||||
@@ -31,10 +31,10 @@ class CounterRoot extends CounterComponent {
|
||||
|
||||
const pod = this.getPod();
|
||||
|
||||
this._$wrpRows = $$`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto relative"/>`;
|
||||
this._$wrpRows = $$`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto relative"></div>`;
|
||||
this._childComps.forEach(it => it.render(this._$wrpRows, pod));
|
||||
|
||||
const $btnAdd = $(`<button class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus"/> Add Counter</button>`)
|
||||
const $btnAdd = $(`<button class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus"></span> Add Counter</button>`)
|
||||
.click(() => {
|
||||
const comp = new CounterRow(this._board, this._$wrpPanel);
|
||||
this._childComps.push(comp);
|
||||
@@ -43,7 +43,7 @@ class CounterRoot extends CounterComponent {
|
||||
});
|
||||
|
||||
$$`<div class="w-100 h-100 ve-flex-col px-2 pb-3">
|
||||
<div class="no-shrink pt-4"/>
|
||||
<div class="no-shrink pt-4"></div>
|
||||
${this._$wrpRows}
|
||||
<div class="no-shrink ve-flex-h-right">${$btnAdd}</div>
|
||||
</div>`.appendTo($parent);
|
||||
@@ -123,13 +123,13 @@ class CounterRow extends CounterComponent {
|
||||
this._addHookBase("max", hookDisplayMinMax);
|
||||
hookDisplayMinMax();
|
||||
|
||||
const $btnDown = $(`<button class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-minus"/></button>`)
|
||||
const $btnDown = $(`<button class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-minus"></span></button>`)
|
||||
.click(() => this._state.current--);
|
||||
|
||||
const $btnUp = $(`<button class="btn btn-success btn-xs"><span class="glyphicon glyphicon-plus"/></button>`)
|
||||
const $btnUp = $(`<button class="btn btn-success btn-xs"><span class="glyphicon glyphicon-plus"></span></button>`)
|
||||
.click(() => this._state.current++);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-danger btn-xxs"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-danger btn-xxs"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
const {removeRow} = this._parent;
|
||||
removeRow(this);
|
||||
|
||||
@@ -85,7 +85,7 @@ export class InitiativeTrackerCreatureViewer extends BaseComponent {
|
||||
title: "Select Tracker",
|
||||
});
|
||||
|
||||
const $selTracker = $(`<select class="form-control input-xs mr-1">
|
||||
const $selTracker = $(`<select class="form-control input-xs mb-2">
|
||||
<option value="-1" disabled>Select tracker</option>
|
||||
${$elesData.map(($e, i) => `<option value="${i}">${$e.data("getSummary")()}</option>`).join("")}
|
||||
</select>`)
|
||||
@@ -107,8 +107,8 @@ export class InitiativeTrackerCreatureViewer extends BaseComponent {
|
||||
${$btnSubmit}
|
||||
`;
|
||||
|
||||
const ixSel = await pGetResolved();
|
||||
if (ixSel == null) return;
|
||||
const [isDataEntered, ixSel] = await pGetResolved();
|
||||
if (!isDataEntered || ixSel == null) return;
|
||||
|
||||
this._setLinkedTrackerFromEle({$eleData: $elesData[ixSel]});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export class DmMapper {
|
||||
static $getMapper (board, state) {
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-map__root dm__panel-bg dm__data-anchor"/>`) // root class used to identify for saving
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-map__root dm__panel-bg dm__data-anchor"></div>`) // root class used to identify for saving
|
||||
.data("getState", () => mapper.getSaveableState());
|
||||
const mapper = new DmMapperRoot(board, $wrpPanel);
|
||||
mapper.setStateFrom(state);
|
||||
|
||||
@@ -23,7 +23,7 @@ export class MoneyConverter {
|
||||
}).reverse();
|
||||
const DEFAULT_CURRENCY = 3;
|
||||
|
||||
const $wrpConverter = $(`<div class="dm_money dm__panel-bg split-column"/>`);
|
||||
const $wrpConverter = $(`<div class="dm_money dm__panel-bg split-column"></div>`);
|
||||
|
||||
const doUpdate = () => {
|
||||
if (!$wrpRows.find(`.dm-money__row`).length) {
|
||||
@@ -144,7 +144,7 @@ export class MoneyConverter {
|
||||
const buildCurrency$Select = (isOutput) => $(`<select class="form-control input-sm" style="padding: 5px">${isOutput ? `<option value="-1">(No conversion)</option>` : ""}${CURRENCY.map((c, i) => `<option value="${i}">${c.n}</option>`).join("")}</select>`);
|
||||
|
||||
const addRow = (currency, count) => {
|
||||
const $row = $(`<div class="dm-money__row"/>`).appendTo($wrpRows);
|
||||
const $row = $(`<div class="dm-money__row"></div>`).appendTo($wrpRows);
|
||||
const $iptCount = $(`<input type="number" step="1" placeholder="Coins" class="form-control input-sm">`).appendTo($row).change(doUpdate);
|
||||
if (count != null) $iptCount.val(count);
|
||||
const $selCurrency = buildCurrency$Select().appendTo($row).change(doUpdate);
|
||||
@@ -155,18 +155,18 @@ export class MoneyConverter {
|
||||
});
|
||||
};
|
||||
|
||||
const $wrpRows = $(`<div class="dm-money__rows"/>`).appendTo($wrpConverter);
|
||||
const $wrpRows = $(`<div class="dm-money__rows"></div>`).appendTo($wrpConverter);
|
||||
|
||||
const $wrpCtrl = $(`<div class="split dm-money__ctrl"/>`).appendTo($wrpConverter);
|
||||
const $wrpCtrlLhs = $(`<div class="dm-money__ctrl__lhs split-child" style="width: 66%;"/>`).appendTo($wrpCtrl);
|
||||
const $wrpBtnAddSettings = $(`<div class="split"/>`).appendTo($wrpCtrlLhs);
|
||||
const $btnAddRow = $(`<button class="btn btn-primary btn-sm" title="Add Row"><span class="glyphicon glyphicon-plus"/></button>`)
|
||||
const $wrpCtrl = $(`<div class="split dm-money__ctrl"></div>`).appendTo($wrpConverter);
|
||||
const $wrpCtrlLhs = $(`<div class="dm-money__ctrl__lhs split-child" style="width: 66%;"></div>`).appendTo($wrpCtrl);
|
||||
const $wrpBtnAddSettings = $(`<div class="split"></div>`).appendTo($wrpCtrlLhs);
|
||||
const $btnAddRow = $(`<button class="btn btn-primary btn-sm" title="Add Row"><span class="glyphicon glyphicon-plus"></span></button>`)
|
||||
.appendTo($wrpBtnAddSettings)
|
||||
.click(() => {
|
||||
addRow();
|
||||
doUpdate();
|
||||
});
|
||||
const $btnSettings = $(`<button class="btn btn-default btn-sm" title="Settings"><span class="glyphicon glyphicon-cog"/></button>`)
|
||||
const $btnSettings = $(`<button class="btn btn-default btn-sm" title="Settings"><span class="glyphicon glyphicon-cog"></span></button>`)
|
||||
.appendTo($wrpBtnAddSettings)
|
||||
.click(() => {
|
||||
const {$modalInner} = UiUtil.getShowModal({
|
||||
@@ -184,7 +184,7 @@ export class MoneyConverter {
|
||||
JqueryUtil.showCopiedEffect($iptOut);
|
||||
});
|
||||
|
||||
const $wrpCtrlRhs = $(`<div class="dm-money__ctrl__rhs split-child" style="width: 33%;"/>`).appendTo($wrpCtrl);
|
||||
const $wrpCtrlRhs = $(`<div class="dm-money__ctrl__rhs split-child" style="width: 33%;"></div>`).appendTo($wrpCtrl);
|
||||
const $iptSplit = $(`<input type="number" min="1" step="1" placeholder="Split Between..." class="form-control input-sm">`).appendTo($wrpCtrlRhs).change(doUpdate);
|
||||
const $selOut = buildCurrency$Select(true).appendTo($wrpCtrlRhs).change(doUpdate);
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import {DmScreenUtil} from "./dmscreen-util.js";
|
||||
// region v1
|
||||
export class InitiativeTrackerPlayerV1 {
|
||||
static $getPanelElement (board, state) {
|
||||
const $meta = $(`<div class="initp__meta"/>`).hide();
|
||||
const $head = $(`<div class="initp__header"/>`).hide();
|
||||
const $meta = $(`<div class="initp__meta"></div>`).hide();
|
||||
const $head = $(`<div class="initp__header"></div>`).hide();
|
||||
const $rows = $(`<div class="ve-flex-col"></div>`).hide();
|
||||
|
||||
const $wrpTracker = $$`<div class="initp__wrp_active">
|
||||
@@ -184,8 +184,8 @@ class InitiativeTrackerPlayerMessageHandlerScreenV1 extends InitiativeTrackerPla
|
||||
// region v0
|
||||
export class InitiativeTrackerPlayerV0 {
|
||||
static $getPanelElement (board, state) {
|
||||
const $meta = $(`<div class="initp__meta"/>`).hide();
|
||||
const $head = $(`<div class="initp__header"/>`).hide();
|
||||
const $meta = $(`<div class="initp__meta"></div>`).hide();
|
||||
const $head = $(`<div class="initp__header"></div>`).hide();
|
||||
const $rows = $(`<div class="ve-flex-col"></div>`).hide();
|
||||
|
||||
const $wrpTracker = $$`<div class="initp__wrp_active">
|
||||
|
||||
@@ -27,7 +27,7 @@ export class TimerTrackerMoonSpriteLoader {
|
||||
|
||||
export class TimeTracker {
|
||||
static $getTracker (board, state) {
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-time__root dm__panel-bg dm__data-anchor"/>`) // root class used to identify for saving
|
||||
const $wrpPanel = $(`<div class="w-100 h-100 dm-time__root dm__panel-bg dm__data-anchor"></div>`) // root class used to identify for saving
|
||||
.data("getState", () => tracker.getSaveableState());
|
||||
const tracker = new TimeTrackerRoot(board, $wrpPanel);
|
||||
state = TimeTrackerUtil.getMigratedState(state);
|
||||
@@ -441,7 +441,7 @@ class TimeTrackerBase extends TimeTrackerComponent {
|
||||
}
|
||||
|
||||
static $getCvsMoon (moonInfo) {
|
||||
const $canvas = $(`<canvas title="${moonInfo.name.escapeQuotes()}\u2014${moonInfo.phaseName}" class="dm-time__cvs-moon" width="${TimeTrackerBase._MOON_RENDER_RES}" height="${TimeTrackerBase._MOON_RENDER_RES}"/>`);
|
||||
const $canvas = $(`<canvas title="${moonInfo.name.escapeQuotes()}\u2014${moonInfo.phaseName}" class="dm-time__cvs-moon" width="${TimeTrackerBase._MOON_RENDER_RES}" height="${TimeTrackerBase._MOON_RENDER_RES}"></canvas>`);
|
||||
const c = $canvas[0];
|
||||
const ctx = c.getContext("2d");
|
||||
|
||||
@@ -694,7 +694,10 @@ class TimeTrackerRoot extends TimeTrackerBase {
|
||||
hookShowTab();
|
||||
|
||||
const $btnReset = $(`<button class="btn btn-xs btn-danger" title="Reset Clock/Calendar Time to First Day"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => confirm("Are you sure?") && Object.assign(this._state, {time: 0, isBrowseMode: false, browseTime: null}));
|
||||
.click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
Object.assign(this._state, {time: 0, isBrowseMode: false, browseTime: null});
|
||||
});
|
||||
|
||||
$$`<div class="ve-flex-col h-100">
|
||||
<div class="ve-flex p-1 no-shrink">
|
||||
@@ -820,11 +823,11 @@ class TimeTrackerRoot_Clock extends TimeTrackerComponent {
|
||||
}, 1000);
|
||||
this._$wrpPanel.data("onDestroy", () => clearInterval(this._ivTimer));
|
||||
|
||||
const $dispReadableDate = $(`<div class="small-caps"/>`);
|
||||
const $dispReadableYear = $(`<div class="small-caps small text-muted mb-2"/>`);
|
||||
const $wrpMoons = $(`<div class="ve-flex ve-flex-wrap w-100 no-shrink ve-flex-vh-center mb-3"/>`);
|
||||
const $dispReadableDate = $(`<div class="small-caps"></div>`);
|
||||
const $dispReadableYear = $(`<div class="small-caps small text-muted mb-2"></div>`);
|
||||
const $wrpMoons = $(`<div class="ve-flex ve-flex-wrap w-100 no-shrink ve-flex-vh-center mb-3"></div>`);
|
||||
|
||||
const $wrpDayNight = $(`<div class="ve-flex w-100 no-shrink ve-flex-h-center ve-flex-v-baseline mt-2"/>`);
|
||||
const $wrpDayNight = $(`<div class="ve-flex w-100 no-shrink ve-flex-h-center ve-flex-v-baseline mt-2"></div>`);
|
||||
|
||||
const getSecsToNextDay = (timeInfo) => {
|
||||
const {
|
||||
@@ -910,12 +913,12 @@ class TimeTrackerRoot_Clock extends TimeTrackerComponent {
|
||||
const $iptMinutes = $getIpt("minutesPerHour", "numMinutes", "secsPerMinute");
|
||||
const $iptSeconds = $getIpt("secondsPerMinute", "numSecs");
|
||||
|
||||
const $wrpDays = $(`<div class="small-caps ve-text-center mb-1"/>`);
|
||||
const $wrpDays = $(`<div class="small-caps ve-text-center mb-1"></div>`);
|
||||
const $wrpHours = $$`<div class="ve-flex ve-flex-vh-center">${$iptHours}</div>`;
|
||||
const $wrpMinutes = $$`<div class="ve-flex ve-flex-vh-center">${$iptMinutes}</div>`;
|
||||
const $wrpSeconds = $$`<div class="ve-flex ve-flex-vh-center">${$iptSeconds}</div>`;
|
||||
|
||||
const $wrpEventsEncounters = $(`<div class="ve-flex-vh-center relative ve-flex-wrap dm-time__wrp-clock-events"/>`);
|
||||
const $wrpEventsEncounters = $(`<div class="ve-flex-vh-center relative ve-flex-wrap dm-time__wrp-clock-events"></div>`);
|
||||
const $hrEventsEncounters = $(`<hr class="hr-2">`);
|
||||
|
||||
// cache rendering
|
||||
@@ -1221,7 +1224,7 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
this._parent = parent;
|
||||
const {getTimeInfo} = parent;
|
||||
|
||||
const $btnRandomise = $(`<button class="btn btn-xxs btn-default dm-time__btn-random-weather" title="Roll Weather (SHIFT to Reroll Using Previous Settings)"><span class="fal fa-dice"/></button>`)
|
||||
const $btnRandomise = $(`<button class="btn btn-xxs btn-default dm-time__btn-random-weather" title="Roll Weather (SHIFT to Reroll Using Previous Settings)"><span class="fal fa-dice"></span></button>`)
|
||||
.click(async evt => {
|
||||
const randomState = await TimeTrackerRoot_Clock_RandomWeather.pGetUserInput(
|
||||
{
|
||||
@@ -1239,7 +1242,7 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
Object.assign(this._state, randomState);
|
||||
});
|
||||
|
||||
const $btnTemperature = $(`<button class="btn btn-default btn-sm dm-time__btn-weather mr-2"/>`)
|
||||
const $btnTemperature = $(`<button class="btn btn-default btn-sm dm-time__btn-weather mr-2"></button>`)
|
||||
.click(async () => {
|
||||
let ixCur = TimeTrackerRoot_Clock_Weather._TEMPERATURES.indexOf(this._state.temperature);
|
||||
if (!~ixCur) ixCur = 2;
|
||||
@@ -1265,12 +1268,12 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
if (!~ix) ix = 0;
|
||||
const meta = TimeTrackerRoot_Clock_Weather._TEMPERATURE_META[ix];
|
||||
$btnTemperature.addClass(meta.class);
|
||||
$btnTemperature.title(this._state.temperature.uppercaseFirst()).html(`<div class="fal ${meta.icon}"/>`);
|
||||
$btnTemperature.title(this._state.temperature.uppercaseFirst()).html(`<div class="fal ${meta.icon}"></div>`);
|
||||
};
|
||||
this._addHookBase("temperature", hookTemperature);
|
||||
hookTemperature();
|
||||
|
||||
const $btnPrecipitation = $(`<button class="btn btn-default btn-sm dm-time__btn-weather mr-2"/>`)
|
||||
const $btnPrecipitation = $(`<button class="btn btn-default btn-sm dm-time__btn-weather mr-2"></button>`)
|
||||
.click(async () => {
|
||||
const {
|
||||
numHours,
|
||||
@@ -1312,13 +1315,13 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
let ix = TimeTrackerRoot_Clock_Weather._PRECIPICATION.indexOf(this._state.precipitation);
|
||||
if (!~ix) ix = 0;
|
||||
const meta = TimeTrackerRoot_Clock_Weather._PRECIPICATION_META[ix];
|
||||
$btnPrecipitation.title(TimeTrackerUtil.revSlugToText(this._state.precipitation)).html(`<div class="fal ${useNightIcon && meta.iconNight ? meta.iconNight : meta.icon}"/>`);
|
||||
$btnPrecipitation.title(TimeTrackerUtil.revSlugToText(this._state.precipitation)).html(`<div class="fal ${useNightIcon && meta.iconNight ? meta.iconNight : meta.icon}"></div>`);
|
||||
};
|
||||
this._addHookBase("precipitation", hookPrecipitation);
|
||||
this._parent.addHook("time", hookPrecipitation);
|
||||
hookPrecipitation();
|
||||
|
||||
const $btnWindDirection = $(`<button class="btn btn-default btn-sm dm-time__btn-weather"/>`)
|
||||
const $btnWindDirection = $(`<button class="btn btn-default btn-sm dm-time__btn-weather"></button>`)
|
||||
.click(async () => {
|
||||
const bearing = await TimeTrackerUtil.pGetUserWindBearing(this._state.windDirection);
|
||||
if (bearing != null) this._state.windDirection = bearing;
|
||||
@@ -1329,14 +1332,14 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
|
||||
if (ixCur) {
|
||||
const speedClass = ixCur >= 5 ? "fas" : ixCur >= 3 ? "far" : "fal";
|
||||
$btnWindDirection.html(`<div class="${speedClass} fa-arrow-up" style="transform: rotate(${this._state.windDirection}deg);"/>`);
|
||||
} else $btnWindDirection.html(`<div class="fal fa-ellipsis-h"/>`);
|
||||
$btnWindDirection.html(`<div class="${speedClass} fa-arrow-up" style="transform: rotate(${this._state.windDirection}deg);"></div>`);
|
||||
} else $btnWindDirection.html(`<div class="fal fa-ellipsis-h"></div>`);
|
||||
};
|
||||
this._addHookBase("windDirection", hookWindDirection);
|
||||
this._addHookBase("windSpeed", hookWindDirection);
|
||||
hookWindDirection();
|
||||
|
||||
const $btnWindSpeed = $(`<button class="btn btn-default btn-xs"/>`)
|
||||
const $btnWindSpeed = $(`<button class="btn btn-default btn-xs"></button>`)
|
||||
.click(async () => {
|
||||
let ixCur = TimeTrackerRoot_Clock_Weather._WIND_SPEEDS.indexOf(this._state.windSpeed);
|
||||
if (!~ixCur) ixCur = 0;
|
||||
@@ -1366,7 +1369,7 @@ class TimeTrackerRoot_Clock_Weather extends TimeTrackerComponent {
|
||||
this._parent.addHook("unitsWindSpeed", hookWindSpeed);
|
||||
hookWindSpeed();
|
||||
|
||||
const $hovEnvEffects = $(`<div><span class="glyphicon glyphicon-info-sign"/></div>`);
|
||||
const $hovEnvEffects = $(`<div><span class="glyphicon glyphicon-info-sign"></span></div>`);
|
||||
const $wrpEnvEffects = $$`<div class="mt-2">${$hovEnvEffects}</div>`;
|
||||
let hoverMetaEnvEffects = null;
|
||||
const hookEnvEffects = () => {
|
||||
@@ -1570,13 +1573,13 @@ class TimeTrackerRoot_Clock_RandomWeather extends BaseComponent {
|
||||
return $btn;
|
||||
});
|
||||
|
||||
const $btnWindDirection = $(`<button class="btn btn-default btn-sm dm-time__btn-weather"/>`)
|
||||
const $btnWindDirection = $(`<button class="btn btn-default btn-sm dm-time__btn-weather"></button>`)
|
||||
.click(async () => {
|
||||
const bearing = await TimeTrackerUtil.pGetUserWindBearing(this._state.prevailingWindDirection);
|
||||
if (bearing != null) this._state.prevailingWindDirection = bearing;
|
||||
});
|
||||
const hookWindDirection = () => {
|
||||
$btnWindDirection.html(`<div class="far fa-arrow-up" style="transform: rotate(${this._state.prevailingWindDirection}deg);"/>`);
|
||||
$btnWindDirection.html(`<div class="far fa-arrow-up" style="transform: rotate(${this._state.prevailingWindDirection}deg);"></div>`);
|
||||
};
|
||||
this._addHookBase("prevailingWindDirection", hookWindDirection);
|
||||
hookWindDirection();
|
||||
@@ -1755,8 +1758,8 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
// cache info to avoid re-rendering the calendar every second
|
||||
let lastRenderMeta = null;
|
||||
|
||||
const $dispDayReadableDate = $(`<div class="small-caps"/>`);
|
||||
const $dispYear = $(`<div class="small-caps text-muted small"/>`);
|
||||
const $dispDayReadableDate = $(`<div class="small-caps"></div>`);
|
||||
const $dispYear = $(`<div class="small-caps text-muted small"></div>`);
|
||||
const {$wrpDateControls, $iptYear, $iptMonth, $iptDay} = TimeTrackerRoot_Calendar.getDateControls(this._parent);
|
||||
|
||||
const $btnBrowseMode = ComponentUiUtil.$getBtnBool(
|
||||
@@ -1771,7 +1774,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
},
|
||||
);
|
||||
|
||||
const $wrpCalendar = $(`<div class="ve-overflow-y-auto smooth-scroll"/>`);
|
||||
const $wrpCalendar = $(`<div class="ve-overflow-y-auto smooth-scroll"></div>`);
|
||||
|
||||
const hookCalendar = (prop) => {
|
||||
const timeInfo = getTimeInfo();
|
||||
@@ -2057,7 +2060,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
|
||||
let $ele;
|
||||
if (i < 0 || i >= daysInMonth) {
|
||||
$ele = $(`<div class="m-1"/>`);
|
||||
$ele = $(`<div class="m-1"></div>`);
|
||||
} else {
|
||||
const eventDay = monthStartDayOfYear + i;
|
||||
const moonDay = numDays - (date - i);
|
||||
@@ -2074,7 +2077,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
return TimeTrackerBase.$getCvsMoon(m).addClass("dm-time__calendar-moon-phase");
|
||||
} else if (i === 1) {
|
||||
const otherMoons = activeMoons.length - 1;
|
||||
return `<div class="dm-time__calendar-moon-phase text-muted" title="${otherMoons} additional moon${otherMoons === 1 ? "" : "s"} not shown"><span class="glyphicon glyphicon-plus"/></div>`;
|
||||
return `<div class="dm-time__calendar-moon-phase text-muted" title="${otherMoons} additional moon${otherMoons === 1 ? "" : "s"} not shown"><span class="glyphicon glyphicon-plus"></span></div>`;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2125,7 +2128,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
doClose();
|
||||
});
|
||||
|
||||
const $btnAddEvent = $(`<button class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"/> Add Event</button>`)
|
||||
const $btnAddEvent = $(`<button class="btn btn-xs btn-primary"><span class="glyphicon glyphicon-plus"></span> Add Event</button>`)
|
||||
.click(() => {
|
||||
const nxtPos = Object.keys(this._parent.get("events")).length;
|
||||
const nuEvent = TimeTrackerBase.getGenericEvent(nxtPos, year, eventDay);
|
||||
@@ -2202,7 +2205,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
}),
|
||||
]);
|
||||
|
||||
const $btnAddEncounter = $(`<button class="btn btn-xs btn-success"><span class="glyphicon glyphicon-plus"/> Add Encounter</button>`)
|
||||
const $btnAddEncounter = $(`<button class="btn btn-xs btn-success"><span class="glyphicon glyphicon-plus"></span> Add Encounter</button>`)
|
||||
.click(evt => ContextUtil.pOpenMenu(evt, menuEncounter));
|
||||
|
||||
const $btnAddEncounterAtTime = $(`<button class="btn btn-xs btn-success">At Time...</button>`)
|
||||
@@ -2221,7 +2224,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
});
|
||||
|
||||
const $hrMoons = $(`<hr class="hr-2 no-shrink">`);
|
||||
const $wrpMoons = $(`<div class="ve-flex ve-flex-wrap w-100 no-shrink ve-flex-v-center"/>`);
|
||||
const $wrpMoons = $(`<div class="ve-flex ve-flex-wrap w-100 no-shrink ve-flex-v-center"></div>`);
|
||||
const hookMoons = () => {
|
||||
const todayMoonInfos = getMoonInfos(moonDay);
|
||||
$wrpMoons.empty();
|
||||
@@ -2239,7 +2242,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
this._parent.addHook("moons", hookMoons);
|
||||
hookMoons();
|
||||
|
||||
const $wrpEvents = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const $wrpEvents = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"></div>`);
|
||||
const hookEvents = () => {
|
||||
const todayEvents = getEvents(year, eventDay);
|
||||
$wrpEvents.empty();
|
||||
@@ -2260,7 +2263,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
this._parent.addHook("events", hookEvents);
|
||||
hookEvents();
|
||||
|
||||
const $wrpEncounters = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const $wrpEncounters = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"></div>`);
|
||||
const hookEncounters = async () => {
|
||||
await this._pLock("encounters");
|
||||
|
||||
@@ -2281,10 +2284,10 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
})
|
||||
.val(encounter.displayName == null ? encounter.name : encounter.displayName);
|
||||
|
||||
const $btnRunEncounter = $(`<button class="btn btn-xs btn-default mr-2 ${encounter.countUses > 0 ? "disabled" : ""}" title="${encounter.countUses > 0 ? "(Encounter has been used)" : "Run Encounter (Add to Initiative Tracker)"}"><span class="glyphicon glyphicon-play"/></button>`)
|
||||
const $btnRunEncounter = $(`<button class="btn btn-xs btn-default mr-2 ${encounter.countUses > 0 ? "disabled" : ""}" title="${encounter.countUses > 0 ? "(Encounter has been used)" : "Run Encounter (Add to Initiative Tracker)"}"><span class="glyphicon glyphicon-play"></span></button>`)
|
||||
.click(() => TimeTrackerRoot_Calendar.pDoRunEncounter(this._parent, encounter));
|
||||
|
||||
const $btnResetUse = $(`<button class="btn btn-xs btn-default mr-2 ${encounter.countUses === 0 ? "disabled" : ""}" title="Reset Usage"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnResetUse = $(`<button class="btn btn-xs btn-default mr-2 ${encounter.countUses === 0 ? "disabled" : ""}" title="Reset Usage"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (encounter.countUses === 0) return;
|
||||
|
||||
@@ -2292,7 +2295,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
this._parent.triggerMapUpdate("encounters");
|
||||
});
|
||||
|
||||
const $btnSaveToFile = $(`<button class="btn btn-xs btn-default mr-3" title="Download Encounter File"><span class="glyphicon glyphicon-download"/></button>`)
|
||||
const $btnSaveToFile = $(`<button class="btn btn-xs btn-default mr-3" title="Download Encounter File"><span class="glyphicon glyphicon-download"></span></button>`)
|
||||
.click(async () => {
|
||||
const toSave = await TimeTrackerRoot_Calendar._pGetDereferencedEncounter(encounter);
|
||||
|
||||
@@ -2332,7 +2335,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
);
|
||||
}
|
||||
|
||||
const $btnMove = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-move" title="Move Encounter"/></button>`)
|
||||
const $btnMove = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-move" title="Move Encounter"></span></button>`)
|
||||
.click(() => {
|
||||
this._render_openDayModal_openCalendarPicker({
|
||||
title: "Choose Encounter Day",
|
||||
@@ -2347,7 +2350,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
});
|
||||
});
|
||||
|
||||
const $btnDelete = $(`<button class="btn btn-xs btn-danger" title="Delete Encounter"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnDelete = $(`<button class="btn btn-xs btn-danger" title="Delete Encounter"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
encounter.isDeleted = true;
|
||||
this._parent.triggerMapUpdate("encounters");
|
||||
@@ -2613,7 +2616,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
|
||||
const {$wrpDateControls, $iptYear, $iptMonth} = TimeTrackerRoot_Calendar.getDateControls(tempPod, {isHideWeeks: true, isHideDays: true});
|
||||
$wrpDateControls.addClass("mb-2").appendTo($modalInner);
|
||||
const $wrpCalendar = $(`<div/>`).appendTo($modalInner);
|
||||
const $wrpCalendar = $(`<div></div>`).appendTo($modalInner);
|
||||
|
||||
const hookCalendar = () => {
|
||||
const timeInfo = tempPod.getTimeInfo();
|
||||
@@ -2750,7 +2753,7 @@ class TimeTrackerRoot_Settings extends TimeTrackerComponent {
|
||||
|
||||
const btnHideHooks = [];
|
||||
const $getBtnHide = (prop, $ele, ...$eles) => {
|
||||
const $btn = $(`<button class="btn btn-xs btn-default" title="Hide Section"><span class="glyphicon glyphicon-eye-close"/></button>`)
|
||||
const $btn = $(`<button class="btn btn-xs btn-default" title="Hide Section"><span class="glyphicon glyphicon-eye-close"></span></button>`)
|
||||
.click(() => this._parent.set(prop, !this._parent.get(prop)));
|
||||
const hook = () => {
|
||||
const isHidden = this._parent.get(prop);
|
||||
@@ -2765,8 +2768,8 @@ class TimeTrackerRoot_Settings extends TimeTrackerComponent {
|
||||
|
||||
const $getBtnReset = (...props) => {
|
||||
return $(`<button class="btn btn-xs btn-default mr-2">Reset Section</button>`)
|
||||
.click(() => {
|
||||
if (!confirm("Are you sure?")) return;
|
||||
.click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
props.forEach(prop => this._parent.set(prop, TimeTrackerBase._DEFAULT_STATE[prop]));
|
||||
});
|
||||
};
|
||||
@@ -2874,7 +2877,7 @@ class TimeTrackerRoot_Settings extends TimeTrackerComponent {
|
||||
<div class="ve-flex w-100 mb-1 mt-1">
|
||||
<div class="w-100 ve-flex-v-center">Name</div>
|
||||
<div class="w-25 no-shrink ve-text-center mr-2">Days</div>
|
||||
<div class="dm-time__spc-drag-header no-shrink mr-2"/>
|
||||
<div class="dm-time__spc-drag-header no-shrink mr-2"></div>
|
||||
${metaMonths.$btnAdd.addClass("no-shrink")}
|
||||
</div>
|
||||
${metaMonths.$wrpRows}
|
||||
@@ -3018,7 +3021,7 @@ class TimeTrackerRoot_Settings extends TimeTrackerComponent {
|
||||
}
|
||||
|
||||
_render_$getBtnAddChild ({prop, name, fnGetGeneric}) {
|
||||
return $(`<button class="btn btn-xs btn-primary" title="Add ${name}"><span class="glyphicon glyphicon-plus"/></button>`)
|
||||
return $(`<button class="btn btn-xs btn-primary" title="Add ${name}"><span class="glyphicon glyphicon-plus"></span></button>`)
|
||||
.click(() => {
|
||||
const nxt = fnGetGeneric(this._parent.get(prop).length);
|
||||
this._parent.set(prop, [...this._parent.get(prop), nxt]);
|
||||
@@ -3046,14 +3049,14 @@ class TimeTrackerRoot_Settings_Day extends RenderableCollectionTimeTracker {
|
||||
|
||||
const $padDrag = DragReorderUiUtil.$getDragPadOpts(() => $wrpRow, this._dragMeta);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Day"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Day"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.days = this._comp._state.days.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1 dm-time__row-delete">
|
||||
${$iptName}
|
||||
${$padDrag}
|
||||
${$btnRemove}
|
||||
<div class="dm-time__spc-button"/>
|
||||
<div class="dm-time__spc-button"></div>
|
||||
</div>`.appendTo(this._$wrpRows);
|
||||
|
||||
return {
|
||||
@@ -3081,7 +3084,7 @@ class TimeTrackerRoot_Settings_Month extends RenderableCollectionTimeTracker {
|
||||
|
||||
const $padDrag = DragReorderUiUtil.$getDragPadOpts(() => $wrpRow, this._dragMeta);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Month"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Month"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.months = this._comp._state.months.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1 dm-time__row-delete">
|
||||
@@ -3089,7 +3092,7 @@ class TimeTrackerRoot_Settings_Month extends RenderableCollectionTimeTracker {
|
||||
${$iptDays}
|
||||
${$padDrag}
|
||||
${$btnRemove}
|
||||
<div class="dm-time__spc-button"/>
|
||||
<div class="dm-time__spc-button"></div>
|
||||
</div>`.appendTo(this._$wrpRows);
|
||||
|
||||
return {
|
||||
@@ -3113,7 +3116,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
$wrpEntries.toggleClass("hidden", !isShown);
|
||||
};
|
||||
|
||||
const $dispEntries = $(`<div class="stats stats--book dm-time__wrp-event-entries"/>`);
|
||||
const $dispEntries = $(`<div class="stats stats--book dm-time__wrp-event-entries"></div>`);
|
||||
const hookEntries = () => {
|
||||
$dispEntries.html(Renderer.get().render({entries: MiscUtil.copy(this._state.entries)}));
|
||||
doShowHideEntries();
|
||||
@@ -3130,7 +3133,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
const hookName = () => $iptName.val(this._state.name || "(Unnamed event)");
|
||||
this._addHookBase("name", hookName);
|
||||
|
||||
const $btnShowHide = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-eye-close"/></button>`)
|
||||
const $btnShowHide = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-eye-close"></span></button>`)
|
||||
.click(() => this._state.isHidden = !this._state.isHidden);
|
||||
const hookShowHide = () => {
|
||||
$btnShowHide.toggleClass("active", !!this._state.isHidden);
|
||||
@@ -3138,7 +3141,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
};
|
||||
this._addHookBase("isHidden", hookShowHide);
|
||||
|
||||
const $btnEdit = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-pencil" title="Edit Event"/></button>`)
|
||||
const $btnEdit = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-pencil" title="Edit Event"></span></button>`)
|
||||
.click(() => this.doOpenEditModal());
|
||||
|
||||
const $cbHasTime = $(`<input type="checkbox">`)
|
||||
@@ -3171,7 +3174,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
);
|
||||
}
|
||||
|
||||
const $btnMove = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-move" title="Move Event"/></button>`)
|
||||
const $btnMove = $(`<button class="btn btn-xs btn-default mr-2 no-shrink"><span class="glyphicon glyphicon-move" title="Move Event"></span></button>`)
|
||||
.click(() => {
|
||||
fnOpenCalendarPicker({
|
||||
title: "Choose Event Day",
|
||||
@@ -3185,7 +3188,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
});
|
||||
});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Event"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Event"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._state.isDeleted = true);
|
||||
|
||||
hookEntries();
|
||||
@@ -3232,7 +3235,7 @@ class TimeTrackerRoot_Settings_Event extends TimeTrackerComponent {
|
||||
});
|
||||
|
||||
const $iptName = ComponentUiUtil.$getIptStr(fauxComponent, "name", {$ele: $(`<input class="form-control input-xs form-control--minimal mb-2 no-shrink">`)});
|
||||
const $iptEntries = ComponentUiUtil.$getIptEntries(fauxComponent, "entries", {$ele: $(`<textarea class="form-control input-xs form-control--minimal resize-none mb-2 h-100"/>`)});
|
||||
const $iptEntries = ComponentUiUtil.$getIptEntries(fauxComponent, "entries", {$ele: $(`<textarea class="form-control input-xs form-control--minimal resize-none mb-2 h-100"></textarea>`)});
|
||||
|
||||
const $btnOk = $(`<button class="btn btn-default">Save</button>`)
|
||||
.click(() => doClose(true));
|
||||
@@ -3281,7 +3284,7 @@ class TimeTrackerRoot_Settings_Season extends RenderableCollectionTimeTracker {
|
||||
const $iptDaysStart = $getIptDays("startDay");
|
||||
const $iptDaysEnd = $getIptDays("endDay");
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Season"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Season"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.seasons = this._comp._state.seasons.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1">
|
||||
@@ -3317,7 +3320,7 @@ class TimeTrackerRoot_Settings_Year extends RenderableCollectionTimeTracker {
|
||||
|
||||
const $iptYear = ComponentUiUtil.$getIptInt(comp, "year", 1, {$ele: $(`<input class="form-control input-xs form-control--minimal text-right mr-2 w-25 no-shrink">`), offset: 1, min: 1});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Year"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Year"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.years = this._comp._state.years.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1">
|
||||
@@ -3353,7 +3356,7 @@ class TimeTrackerRoot_Settings_Era extends RenderableCollectionTimeTracker {
|
||||
const $iptYearsStart = $getIptYears("startYear");
|
||||
const $iptYearsEnd = $getIptYears("endYear");
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Year"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Year"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.eras = this._comp._state.eras.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1">
|
||||
@@ -3389,7 +3392,7 @@ class TimeTrackerRoot_Settings_Moon extends RenderableCollectionTimeTracker {
|
||||
const $iptPhaseOffset = ComponentUiUtil.$getIptInt(comp, "phaseOffset", 0, {$ele: $(`<input class="form-control input-xs form-control--minimal text-right mr-2 w-25 no-shrink">`)});
|
||||
const $iptPeriod = ComponentUiUtil.$getIptInt(comp, "period", 1, {$ele: $(`<input class="form-control input-xs form-control--minimal text-right mr-2 w-25 no-shrink">`), min: TimeTrackerBase._MIN_TIME, max: TimeTrackerBase._MAX_TIME});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Moon"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger no-shrink" title="Delete Moon"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => this._comp._state.moons = this._comp._state.moons.filter(it => it !== entity));
|
||||
|
||||
const $wrpRow = $$`<div class="ve-flex my-1">
|
||||
|
||||
@@ -13,15 +13,12 @@ class PageFilterBackgrounds extends PageFilter {
|
||||
super();
|
||||
|
||||
this._skillFilter = new Filter({header: "Skill Proficiencies", displayFn: StrUtil.toTitleCase});
|
||||
this._toolFilter = new Filter({header: "Tool Proficiencies", displayFn: PageFilterBackgrounds._getToolDisplayText.bind(PageFilterBackgrounds)});
|
||||
this._languageFilter = new Filter({
|
||||
header: "Language Proficiencies",
|
||||
displayFn: it => it === "anyStandard"
|
||||
? "Any Standard"
|
||||
: it === "anyExotic"
|
||||
? "Any Exotic"
|
||||
: StrUtil.toTitleCase(it),
|
||||
this._prereqFilter = new Filter({
|
||||
header: "Prerequisite",
|
||||
items: [...FilterCommon.PREREQ_FILTER_ITEMS],
|
||||
});
|
||||
this._toolFilter = new Filter({header: "Tool Proficiencies", displayFn: PageFilterBackgrounds._getToolDisplayText.bind(PageFilterBackgrounds)});
|
||||
this._languageFilter = FilterCommon.getLanguageProficienciesFilter();
|
||||
this._asiFilter = new AbilityScoreFilter({header: "Ability Scores"});
|
||||
this._otherBenefitsFilter = new Filter({header: "Other Benefits"});
|
||||
this._miscFilter = new Filter({header: "Miscellaneous", items: ["Has Info", "Has Images", "SRD", "Basic Rules", "Legacy"], isMiscFilter: true});
|
||||
@@ -30,6 +27,8 @@ class PageFilterBackgrounds extends PageFilter {
|
||||
static mutateForFilters (bg) {
|
||||
bg._fSources = SourceFilter.getCompleteFilterSources(bg);
|
||||
|
||||
bg._fPrereq = FilterCommon.getFilterValuesPrerequisite(bg.prerequisite);
|
||||
|
||||
const {summary: skillDisplay, collection: skills} = Renderer.generic.getSkillSummary({
|
||||
skillProfs: bg.skillProficiencies,
|
||||
skillToolLanguageProfs: bg.skillToolLanguageProficiencies,
|
||||
@@ -69,6 +68,7 @@ class PageFilterBackgrounds extends PageFilter {
|
||||
if (isExcluded) return;
|
||||
|
||||
this._sourceFilter.addItem(bg._fSources);
|
||||
this._prereqFilter.addItem(bg._fPrereq);
|
||||
this._skillFilter.addItem(bg._fSkills);
|
||||
this._toolFilter.addItem(bg._fTools);
|
||||
this._languageFilter.addItem(bg._fLangs);
|
||||
@@ -79,6 +79,7 @@ class PageFilterBackgrounds extends PageFilter {
|
||||
async _pPopulateBoxOptions (opts) {
|
||||
opts.filters = [
|
||||
this._sourceFilter,
|
||||
this._prereqFilter,
|
||||
this._skillFilter,
|
||||
this._toolFilter,
|
||||
this._languageFilter,
|
||||
@@ -92,6 +93,7 @@ class PageFilterBackgrounds extends PageFilter {
|
||||
return this._filterBox.toDisplay(
|
||||
values,
|
||||
bg._fSources,
|
||||
bg._fPrereq,
|
||||
bg._fSkills,
|
||||
bg._fTools,
|
||||
bg._fLangs,
|
||||
|
||||
@@ -37,6 +37,8 @@ class FilterCommon {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _CONDS = [
|
||||
"blinded",
|
||||
"charmed",
|
||||
@@ -67,6 +69,8 @@ class FilterCommon {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static mutateForFilters_damageVulnResImmune_player (ent) {
|
||||
this.mutateForFilters_damageVuln_player(ent);
|
||||
this.mutateForFilters_damageRes_player(ent);
|
||||
@@ -109,6 +113,49 @@ class FilterCommon {
|
||||
if (typeof it === "string") return allSet.add(it);
|
||||
if (it.choose?.from) it.choose?.from.forEach(itSub => this._recurseResVulnImm(allSet, itSub));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static PREREQ_FILTER_ITEMS = ["Ability", "Race", "Psionics", "Proficiency", "Special", "Spellcasting"];
|
||||
|
||||
static _PREREQ_KEY_TO_FULL = {
|
||||
"other": "Special",
|
||||
"otherSummary": "Special",
|
||||
"spellcasting2020": "Spellcasting",
|
||||
"spellcastingFeature": "Spellcasting",
|
||||
"spellcastingPrepared": "Spellcasting",
|
||||
"level": "Class", // We assume that any filter with meaningful level requirements will have these in a separate filter
|
||||
"itemType": "Item Type",
|
||||
"itemProperty": "Item Property",
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Array<object>} prerequisite
|
||||
* @param {Set} ignoredKeys
|
||||
*/
|
||||
static getFilterValuesPrerequisite (prerequisite, {ignoredKeys = null} = {}) {
|
||||
return Array.from(
|
||||
new Set((prerequisite || [])
|
||||
.flatMap(it => Object.keys(it))),
|
||||
)
|
||||
.filter(k => ignoredKeys == null || !ignoredKeys.has(k))
|
||||
.map(it => (this._PREREQ_KEY_TO_FULL[it] || it).uppercaseFirst());
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _LANG_TO_DISPLAY = {
|
||||
"anyStandard": "Any Standard",
|
||||
"anyExotic": "Any Exotic",
|
||||
"anyLanguage": "Any",
|
||||
};
|
||||
|
||||
static getLanguageProficienciesFilter () {
|
||||
return new Filter({
|
||||
header: "Language Proficiencies",
|
||||
displayFn: it => this._LANG_TO_DISPLAY[it] || StrUtil.toTitleCase(it),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
globalThis.FilterCommon = FilterCommon;
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
|
||||
class PageFilterFeats extends PageFilter {
|
||||
// region static
|
||||
static _PREREQ_KEY_TO_FULL = {
|
||||
"other": "Special",
|
||||
"spellcasting2020": "Spellcasting",
|
||||
"spellcastingFeature": "Spellcasting",
|
||||
"spellcastingPrepared": "Spellcasting",
|
||||
};
|
||||
static _PREREQ_KEYs_OTHER_IGNORED = new Set(["level"]);
|
||||
// endregion
|
||||
|
||||
constructor () {
|
||||
@@ -32,7 +27,7 @@ class PageFilterFeats extends PageFilter {
|
||||
});
|
||||
this._otherPrereqFilter = new Filter({
|
||||
header: "Other",
|
||||
items: ["Ability", "Race", "Psionics", "Proficiency", "Special", "Spellcasting"],
|
||||
items: [...FilterCommon.PREREQ_FILTER_ITEMS],
|
||||
});
|
||||
this._levelFilter = new Filter({
|
||||
header: "Level",
|
||||
@@ -64,9 +59,12 @@ class PageFilterFeats extends PageFilter {
|
||||
|
||||
const prereqText = Renderer.utils.prerequisite.getHtml(feat.prerequisite, {isListMode: true}) || VeCt.STR_NONE;
|
||||
|
||||
feat._fPrereqOther = [...new Set((feat.prerequisite || []).flatMap(it => Object.keys(it)))]
|
||||
.map(it => (this._PREREQ_KEY_TO_FULL[it] || it).uppercaseFirst());
|
||||
if (feat.prerequisite) feat._fPrereqLevel = feat.prerequisite.filter(it => it.level != null).map(it => `Level ${it.level.level ?? it.level}`);
|
||||
feat._fPrereqOther = FilterCommon.getFilterValuesPrerequisite(feat.prerequisite, {ignoredKeys: this._PREREQ_KEYs_OTHER_IGNORED});
|
||||
feat._fPrereqLevel = feat.prerequisite
|
||||
? feat.prerequisite
|
||||
.filter(it => it.level != null)
|
||||
.map(it => `Level ${it.level.level ?? it.level}`)
|
||||
: [];
|
||||
feat._fBenifits = [
|
||||
feat.resist ? "Damage Resistance" : null,
|
||||
feat.immune ? "Damage Immunity" : null,
|
||||
@@ -102,7 +100,8 @@ class PageFilterFeats extends PageFilter {
|
||||
|
||||
this._sourceFilter.addItem(feat.source);
|
||||
this._categoryFilter.addItem(feat.category);
|
||||
if (feat.prerequisite) this._levelFilter.addItem(feat._fPrereqLevel);
|
||||
this._levelFilter.addItem(feat._fPrereqLevel);
|
||||
this._otherPrereqFilter.addItem(feat._fPrereqOther);
|
||||
this._vulnerableFilter.addItem(feat._fVuln);
|
||||
this._resistFilter.addItem(feat._fRes);
|
||||
this._immuneFilter.addItem(feat._fImm);
|
||||
|
||||
@@ -5330,6 +5330,9 @@ class MultiFilter extends FilterBase {
|
||||
if (!this.__$wrpFilter) return;
|
||||
this.__$wrpFilter.toggleClass("fltr__hidden--search", numVisible === 0);
|
||||
}
|
||||
|
||||
_doTeardown () { this._filters.forEach(it => it._doTeardown()); }
|
||||
trimState_ () { this._filters.forEach(it => it.trimState_()); }
|
||||
}
|
||||
MultiFilter._DETAULT_STATE = {
|
||||
mode: "and",
|
||||
|
||||
@@ -61,7 +61,7 @@ class LangDemoUi {
|
||||
.change(() => saveContext())
|
||||
.val(value);
|
||||
|
||||
const $btnDel = $(`<button class="btn btn-xs btn-danger" tabindex="-1"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnDel = $(`<button class="btn btn-xs btn-danger" tabindex="-1"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
const ix = LangDemoUi._metasContext.indexOf(out);
|
||||
if (~ix) {
|
||||
|
||||
@@ -119,7 +119,7 @@ class LanguagesPage extends ListPage {
|
||||
fnPopulate: () => {
|
||||
this._$pgContent.empty().append(Renderer.utils.getBorderTr());
|
||||
this._$pgContent.append(Renderer.utils.getNameTr(ent));
|
||||
const $td = $(`<td colspan="6" class="text"/>`);
|
||||
const $td = $(`<td colspan="6" class="text"></td>`);
|
||||
$$`<tr class="text">${$td}</tr>`.appendTo(this._$pgContent);
|
||||
this._$pgContent.append(Renderer.utils.getBorderTr());
|
||||
|
||||
@@ -130,7 +130,7 @@ class LanguagesPage extends ListPage {
|
||||
return;
|
||||
}
|
||||
|
||||
const $styleFont = $(`<style/>`);
|
||||
const $styleFont = $(`<style></style>`);
|
||||
|
||||
let lastStyleIndex = null;
|
||||
let lastStyleClass = null;
|
||||
|
||||
@@ -800,7 +800,7 @@ function sectFamily () {
|
||||
let famIndex = 1;
|
||||
const $btnSuppFam = $(`<button class="btn btn-xs btn-default btn-supp-fam no-print"></button>`).on("click", async () => {
|
||||
const supDetails = await getPersonDetails();
|
||||
const $wrpRes = $(`<div class="life__output-wrp-border p-3 my-2"/>`);
|
||||
const $wrpRes = $(`<div class="life__output-wrp-border p-3 my-2"></div>`);
|
||||
$wrpRes.append(`<h5 class="mt-0">Family Member Roll ${famIndex++}</h5>`);
|
||||
$wrpRes.append(joinParaList(supDetails));
|
||||
$btnSuppFam.css("margin-bottom", 5);
|
||||
|
||||
@@ -2006,7 +2006,7 @@ class ListPage {
|
||||
];
|
||||
const menu = ContextUtil.getMenu(actions);
|
||||
|
||||
const $btnOptions = $(`<button class="btn btn-default btn-xs btn-stats-name" title="Other Options"><span class="glyphicon glyphicon-option-vertical"/></button>`)
|
||||
const $btnOptions = $(`<button class="btn btn-default btn-xs btn-stats-name" title="Other Options"><span class="glyphicon glyphicon-option-vertical"></span></button>`)
|
||||
.click(evt => ContextUtil.pOpenMenu(evt, menu));
|
||||
|
||||
return $$`<div class="ve-flex-v-center btn-group ml-2">${$btnOptions}</div>`;
|
||||
@@ -2204,7 +2204,7 @@ class ListPageBookView extends BookModeViewBase {
|
||||
|
||||
if (i < parts.length - 1) {
|
||||
if ((charLimit -= part.length) < 0) {
|
||||
if (RendererMarkdown.getSetting("isAddPageBreaks")) out.push("", "\\pagebreak", "");
|
||||
if (VetoolsConfig.get("markdown", "isAddPageBreaks")) out.push("", "\\pagebreak", "");
|
||||
charLimit = RendererMarkdown.CHARS_PER_PAGE;
|
||||
}
|
||||
}
|
||||
@@ -2217,13 +2217,13 @@ class ListPageBookView extends BookModeViewBase {
|
||||
const $btnDownloadMarkdown = $(`<button class="btn btn-default btn-sm">Download as Markdown</button>`)
|
||||
.click(() => DataUtil.userDownloadText(`${UrlUtil.getCurrentPage().replace(".html", "")}.md`, this._getVisibleAsMarkdown()));
|
||||
|
||||
const $btnCopyMarkdown = $(`<button class="btn btn-default btn-sm px-2" title="Copy Markdown to Clipboard"><span class="glyphicon glyphicon-copy"/></button>`)
|
||||
const $btnCopyMarkdown = $(`<button class="btn btn-default btn-sm px-2" title="Copy Markdown to Clipboard"><span class="glyphicon glyphicon-copy"></span></button>`)
|
||||
.click(async () => {
|
||||
await MiscUtil.pCopyTextToClipboard(this._getVisibleAsMarkdown());
|
||||
JqueryUtil.showCopiedEffect($btnCopyMarkdown);
|
||||
});
|
||||
|
||||
const $btnDownloadMarkdownSettings = $(`<button class="btn btn-default btn-sm px-2" title="Markdown Settings"><span class="glyphicon glyphicon-cog"/></button>`)
|
||||
const $btnDownloadMarkdownSettings = $(`<button class="btn btn-default btn-sm px-2" title="Markdown Settings"><span class="glyphicon glyphicon-cog"></span></button>`)
|
||||
.click(async () => RendererMarkdown.pShowSettingsModal());
|
||||
|
||||
return $$`<div class="ve-flex-v-center btn-group ml-3">
|
||||
|
||||
@@ -783,7 +783,7 @@ class CreatureBuilder extends Builder {
|
||||
return $selType.val();
|
||||
};
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
chooseTypeRows.splice(chooseTypeRows.indexOf(out), 1);
|
||||
$wrp.empty().remove();
|
||||
@@ -830,7 +830,7 @@ class CreatureBuilder extends Builder {
|
||||
setState();
|
||||
}
|
||||
});
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
tagRows.splice(tagRows.indexOf(out), 1);
|
||||
$wrp.empty().remove();
|
||||
@@ -918,7 +918,7 @@ class CreatureBuilder extends Builder {
|
||||
|
||||
const alignmentRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
|
||||
if ((this._state.alignment && this._state.alignment.some(it => it && (it.special != null || it.alignment !== undefined))) || !~CreatureBuilder.__$getAlignmentInput__getAlignmentIx(this._state.alignment)) {
|
||||
this._state.alignment.forEach(alignment => CreatureBuilder.__$getAlignmentInput__getAlignmentRow(doUpdateState, alignmentRows, alignment).$wrp.appendTo($wrpRows));
|
||||
@@ -926,7 +926,7 @@ class CreatureBuilder extends Builder {
|
||||
CreatureBuilder.__$getAlignmentInput__getAlignmentRow(doUpdateState, alignmentRows, this._state.alignment).$wrp.appendTo($wrpRows);
|
||||
}
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Alignment</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -1018,7 +1018,7 @@ class CreatureBuilder extends Builder {
|
||||
const $stageSpecial = $$`<div>${$iptSpecial}</div>`.toggleVe(initialMode === "2");
|
||||
initialMode === "2" && alignment && $iptSpecial.val(alignment.special);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row mb-2" title="Remove Alignment"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row mb-2" title="Remove Alignment"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
alignmentRows.splice(alignmentRows.indexOf(out), 1);
|
||||
$wrp.empty().remove();
|
||||
@@ -1045,10 +1045,10 @@ class CreatureBuilder extends Builder {
|
||||
|
||||
const acRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
this._state.ac.forEach(ac => CreatureBuilder.__$getAcInput__getAcRow(ac, acRows, doUpdateState).$wrp.appendTo($wrpRows));
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Armor Class Source</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -1152,7 +1152,7 @@ class CreatureBuilder extends Builder {
|
||||
// "FROM" CONTROLS
|
||||
const fromRows = [];
|
||||
|
||||
const $wrpFromRows = $(`<div/>`);
|
||||
const $wrpFromRows = $(`<div></div>`);
|
||||
if (ac && ac.from) ac.from.forEach(f => CreatureBuilder.__$getAcInput__getFromRow(f, fromRows, doUpdateState).$wrpFrom.appendTo($wrpFromRows));
|
||||
|
||||
const $btnAddFrom = $(`<button class="btn btn-xs btn-default mb-2">Add Another Feature/Item</button>`)
|
||||
@@ -1166,7 +1166,7 @@ class CreatureBuilder extends Builder {
|
||||
</div>`.toggleVe(initialMode === "1");
|
||||
|
||||
// REMOVE CONTROLS
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row mb-2" title="Remove AC Source"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row mb-2" title="Remove AC Source"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
acRows.splice(acRows.indexOf(out), 1);
|
||||
$wrp.empty().remove();
|
||||
@@ -1224,7 +1224,7 @@ class CreatureBuilder extends Builder {
|
||||
searchWidget.doFocus();
|
||||
});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row--nested-1 ml-2" title="Remove AC Feature/Item"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row--nested-1 ml-2" title="Remove AC Feature/Item"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
fromRows.splice(fromRows.indexOf(outFrom), 1);
|
||||
$wrpFrom.empty().remove();
|
||||
@@ -1343,7 +1343,7 @@ class CreatureBuilder extends Builder {
|
||||
doUpdateState();
|
||||
});
|
||||
|
||||
const $btnAutoSimpleFormula = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpModifier ? "active" : ""}" title="Auto-calculate modifier from Constitution"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnAutoSimpleFormula = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpModifier ? "active" : ""}" title="Auto-calculate modifier from Constitution"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (this._meta.autoCalc.hpModifier) {
|
||||
this._meta.autoCalc.hpModifier = false;
|
||||
@@ -1362,7 +1362,7 @@ class CreatureBuilder extends Builder {
|
||||
doUpdateState();
|
||||
});
|
||||
|
||||
const $btnAutoSimpleAverage = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpAverageSimple ? "active" : ""}" title="Auto-calculate"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnAutoSimpleAverage = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpAverageSimple ? "active" : ""}" title="Auto-calculate"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (this._meta.autoCalc.hpAverageSimple) {
|
||||
this._meta.autoCalc.hpAverageSimple = false;
|
||||
@@ -1415,7 +1415,7 @@ class CreatureBuilder extends Builder {
|
||||
doUpdateState();
|
||||
});
|
||||
|
||||
const $btnAutoComplexAverage = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpAverageComplex ? "active" : ""}" title="Auto-calculate from Formula"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnAutoComplexAverage = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.hpAverageComplex ? "active" : ""}" title="Auto-calculate from Formula"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (this._meta.autoCalc.hpAverageComplex) {
|
||||
this._meta.autoCalc.hpAverageComplex = false;
|
||||
@@ -1732,7 +1732,7 @@ class CreatureBuilder extends Builder {
|
||||
})
|
||||
.val(this._state.passive || 0);
|
||||
|
||||
const $btnAuto = $(`<button class="btn btn-default btn-xs ${this._meta.autoCalc.passivePerception ? "active" : ""}" title="Auto-Calculate Passive Perception"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnAuto = $(`<button class="btn btn-default btn-xs ${this._meta.autoCalc.passivePerception ? "active" : ""}" title="Auto-Calculate Passive Perception"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (this._meta.autoCalc.passivePerception) {
|
||||
delete this._meta.autoCalc.passivePerception;
|
||||
@@ -1770,8 +1770,8 @@ class CreatureBuilder extends Builder {
|
||||
const [$row, $rowInner] = BuilderUi.getLabelledRowTuple(rowName, {isMarked: true});
|
||||
|
||||
const groups = [];
|
||||
const $wrpGroups = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpControls = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpGroups = $(`<div></div>`).appendTo($rowInner);
|
||||
const $wrpControls = $(`<div></div>`).appendTo($rowInner);
|
||||
|
||||
const doUpdateState = () => {
|
||||
const out = groups.map(it => it.getState());
|
||||
@@ -1866,20 +1866,20 @@ class CreatureBuilder extends Builder {
|
||||
.change(() => doUpdateState());
|
||||
const $iptNotePost = $(`<input class="form-control input-xs form-control--minimal mr-2" placeholder="Post- note">`)
|
||||
.change(() => doUpdateState());
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row" title="Remove ${shortName} Group"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mkbru__btn-rm-row" title="Remove ${shortName} Group"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
groups.splice(groups.indexOf(out), 1);
|
||||
$ele.remove();
|
||||
doUpdateState();
|
||||
});
|
||||
|
||||
const $wrpChildren = $(`<div class="ve-flex-col"/>`);
|
||||
const $wrpChildren = $(`<div class="ve-flex-col"></div>`);
|
||||
const $wrpControls = $$`<div class="mb-2 ve-flex-v-center">${$btnAddChild}${$btnAddChildGroup}${$iptNotePre}${$iptNotePost}${$btnRemove}</div>`;
|
||||
|
||||
const $ele = (() => {
|
||||
const $base = $$`<div class="ve-flex-col ${depth ? "" : "mkbru__wrp-rows"}">${$wrpControls}${$wrpChildren}</div>`;
|
||||
if (!depth) return $base;
|
||||
else return $$`<div class="ve-flex-v-center w-100"><div class="mkbru_mon__row-indent"/>${$base}</div>`;
|
||||
else return $$`<div class="ve-flex-v-center w-100"><div class="mkbru_mon__row-indent"></div>${$base}</div>`;
|
||||
})();
|
||||
|
||||
if (initial) {
|
||||
@@ -1897,7 +1897,7 @@ class CreatureBuilder extends Builder {
|
||||
}
|
||||
|
||||
static __$getDefencesInput__getNodeItem (shortName, children, doUpdateState, type, value) {
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove ${shortName} Entry"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove ${shortName} Entry"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
children.splice(children.indexOf(out), 1);
|
||||
$ele.remove();
|
||||
@@ -2159,7 +2159,7 @@ class CreatureBuilder extends Builder {
|
||||
cb();
|
||||
});
|
||||
|
||||
const $btnAuto = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.proficiency ? "active" : ""}" title="Auto-calculate from Challenge Rating (DMG p. 274)"><span class="glyphicon glyphicon-refresh"/></button>`)
|
||||
const $btnAuto = $(`<button class="btn btn-xs btn-default ${this._meta.autoCalc.proficiency ? "active" : ""}" title="Auto-calculate from Challenge Rating (DMG p. 274)"><span class="glyphicon glyphicon-refresh"></span></button>`)
|
||||
.click(() => {
|
||||
if (this._meta.autoCalc.proficiency) {
|
||||
this._meta.autoCalc.proficiency = false;
|
||||
@@ -2203,8 +2203,8 @@ class CreatureBuilder extends Builder {
|
||||
const [$row, $rowInner] = BuilderUi.getLabelledRowTuple("Spellcasting", {isMarked: true});
|
||||
|
||||
const traitRows = [];
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpControls = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
const $wrpControls = $(`<div></div>`).appendTo($rowInner);
|
||||
|
||||
const $btnAddRow = $(`<button class="btn btn-xs btn-default">Add Spellcasting Trait</button>`)
|
||||
.appendTo($wrpControls)
|
||||
@@ -2391,12 +2391,12 @@ class CreatureBuilder extends Builder {
|
||||
const $btnAddSpell = $(`<button class="btn btn-xs btn-default">Add...</button>`)
|
||||
.click((evt) => ContextUtil.pOpenMenu(evt, menu));
|
||||
|
||||
const $iptHeader = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2" placeholder="Header text"/>`)
|
||||
const $iptHeader = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2" placeholder="Header text"></textarea>`)
|
||||
.toggleVe(!!(trait && trait.headerEntries))
|
||||
.change(() => doUpdateState());
|
||||
if (trait && trait.headerEntries) $iptHeader.val(UiUtil.getEntriesAsText(trait.headerEntries));
|
||||
|
||||
const $iptFooter = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2" placeholder="Footer text"/>`)
|
||||
const $iptFooter = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2" placeholder="Footer text"></textarea>`)
|
||||
.toggleVe(!!(trait && trait.footerEntries))
|
||||
.change(() => doUpdateState());
|
||||
if (trait && trait.footerEntries) $iptFooter.val(UiUtil.getEntriesAsText(trait.footerEntries));
|
||||
@@ -2405,12 +2405,14 @@ class CreatureBuilder extends Builder {
|
||||
const $wrpSubRows = $$`<div class="ve-flex-col"></div>`;
|
||||
const $wrpSubRowsOuter = $$`<div class="ve-flex-col">${$iptHeader}${$wrpSubRows}${$iptFooter}</div>`;
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Trait"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
.click(() => {
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Trait"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(async () => {
|
||||
const currState = getState();
|
||||
if (currState) {
|
||||
delete currState.name; // ignore name key
|
||||
if ((currState.headerEntries || currState.footerEntries || Object.keys(currState).some(it => it !== "headerEntries" && it !== "footerEntries")) && !confirm("Are you sure?")) return;
|
||||
if ((currState.headerEntries || currState.footerEntries || Object.keys(currState).some(it => it !== "headerEntries" && it !== "footerEntries"))) {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Remove Trait", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
}
|
||||
}
|
||||
|
||||
traitRows.splice(traitRows.indexOf(out), 1);
|
||||
@@ -2471,9 +2473,9 @@ class CreatureBuilder extends Builder {
|
||||
} else return null;
|
||||
};
|
||||
|
||||
const $wrpItems = $(`<div class="ve-flex-col"/>`);
|
||||
const $wrpItems = $(`<div class="ve-flex-col"></div>`);
|
||||
|
||||
const $btnAdd = $(`<button class="btn btn-xxs btn-default mr-2" title="Add Spell"><span class="glyphicon glyphicon-plus"/></button>`)
|
||||
const $btnAdd = $(`<button class="btn btn-xxs btn-default mr-2" title="Add Spell"><span class="glyphicon glyphicon-plus"></span></button>`)
|
||||
.click(async () => {
|
||||
const options = {};
|
||||
|
||||
@@ -2489,7 +2491,7 @@ class CreatureBuilder extends Builder {
|
||||
}
|
||||
});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove Spell Group"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove Spell Group"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
spellRows.splice(spellRows.indexOf(out), 1);
|
||||
$ele.empty().remove();
|
||||
@@ -2568,7 +2570,7 @@ class CreatureBuilder extends Builder {
|
||||
out.$ele = $$`<div class="ve-flex mkbru_mon__spell-header-wrp mr-4">
|
||||
<div class="italic">${Parser.spLevelToFull(meta.level)}-level Spells</div>
|
||||
<div class="ve-flex-v-center text-muted small ml-auto"><span>(</span>${$iptSlots}<span class="mr-2">Slots</span></div>
|
||||
<div class="mkbru_mon__spell-header-divider mr-2"/>
|
||||
<div class="mkbru_mon__spell-header-divider mr-2"></div>
|
||||
<label class="ve-flex-v-center text-muted small"><span class="mr-1">Warlock?</span>${$cbWarlock}<span>)</span></label>
|
||||
</div>`;
|
||||
out.getKeyPath = () => ["spells", `${meta.level}`, "spells"];
|
||||
@@ -2597,7 +2599,7 @@ class CreatureBuilder extends Builder {
|
||||
<div class="ve-flex-v-center mkbru__wrp-btn-xxs">${$btnAdd}${$btnRemove}</div>
|
||||
</div>
|
||||
${$wrpItems}
|
||||
<div class="mkbru_mon__spell-divider mb-2"/>
|
||||
<div class="mkbru_mon__spell-divider mb-2"></div>
|
||||
</div>`;
|
||||
|
||||
if (data) data.forEach(spell => addItem(spell));
|
||||
@@ -2618,7 +2620,7 @@ class CreatureBuilder extends Builder {
|
||||
})
|
||||
.hideVe();
|
||||
|
||||
const $btnToggleEdit = $(`<button class="btn btn-xxs btn-default mr-2" title="Toggle Edit Mode"><span class="glyphicon glyphicon-pencil"/></button>`)
|
||||
const $btnToggleEdit = $(`<button class="btn btn-xxs btn-default mr-2" title="Toggle Edit Mode"><span class="glyphicon glyphicon-pencil"></span></button>`)
|
||||
.click(() => {
|
||||
$btnToggleEdit.toggleClass("active");
|
||||
$iptSpell.toggleVe($btnToggleEdit.hasClass("active"));
|
||||
@@ -2627,7 +2629,7 @@ class CreatureBuilder extends Builder {
|
||||
|
||||
const $wrpRender = $(`<div class="mr-2">${getHtml()}</div>`);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove Spell"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xxs btn-danger" title="Remove Spell"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
rowItems.splice(rowItems.indexOf(out), 1);
|
||||
$ele.empty().remove();
|
||||
@@ -2785,8 +2787,9 @@ class CreatureBuilder extends Builder {
|
||||
});
|
||||
|
||||
const $btnReset = $(`<button class="btn btn-sm btn-danger">Reset</button>`)
|
||||
.click(() => {
|
||||
if (!confirm("Are you sure?")) return;
|
||||
.click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
|
||||
setState({
|
||||
iptName: "",
|
||||
cbMelee: true,
|
||||
@@ -3018,11 +3021,11 @@ class CreatureBuilder extends Builder {
|
||||
|
||||
const entryRows = [];
|
||||
|
||||
const $wrpRowsOuter = $(`<div class="relative"/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div/>`).appendTo($wrpRowsOuter);
|
||||
const $wrpRowsOuter = $(`<div class="relative"></div>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($wrpRowsOuter);
|
||||
const rowOptions = {prop: options.prop, shortName: options.shortName, $wrpRowsOuter};
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add ${options.shortName}</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -3096,15 +3099,17 @@ class CreatureBuilder extends Builder {
|
||||
$wrpRowsOuter: options.$wrpRowsOuter,
|
||||
}) : null;
|
||||
|
||||
const $iptEntries = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2"/>`)
|
||||
const $iptEntries = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2"></textarea>`)
|
||||
.change(() => doUpdateState());
|
||||
|
||||
if (entry && entry.entries) $iptEntries.val(UiUtil.getEntriesAsText(entry.entries));
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mb-2" title="Remove ${options.shortName}"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
.click(() => {
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger mb-2" title="Remove ${options.shortName}"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(async () => {
|
||||
const currState = getState();
|
||||
if (currState && currState.entries && !confirm("Are you sure?")) return;
|
||||
if (currState && currState.entries) {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: `Remove ${options.shortName}`, htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
}
|
||||
entryRows.splice(entryRows.indexOf(out), 1);
|
||||
$ele.empty().remove();
|
||||
doUpdateState();
|
||||
@@ -3364,7 +3369,7 @@ class CreatureBuilder extends Builder {
|
||||
cb();
|
||||
};
|
||||
|
||||
const $wrpIpts = $(`<div class="ve-flex-col w-100 mr-2"/>`);
|
||||
const $wrpIpts = $(`<div class="ve-flex-col w-100 mr-2"></div>`);
|
||||
const inputs = [];
|
||||
Parser.ENVIRONMENTS.forEach(val => {
|
||||
const $cb = $(`<input class="mkbru__ipt-cb mkbru_mon__cb-environment" type="checkbox">`)
|
||||
@@ -3403,7 +3408,7 @@ class CreatureBuilder extends Builder {
|
||||
const $cb = $(`<input class="mkbru__ipt-cb hidden" type="checkbox">`)
|
||||
.prop("checked", true);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-danger btn-xxs"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-danger btn-xxs"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
out.$ele.remove();
|
||||
envRows.splice(envRows.indexOf(out), 1);
|
||||
@@ -3480,11 +3485,11 @@ class CreatureBuilder extends Builder {
|
||||
tabs.forEach(it => it.$wrpTab.appendTo($wrp));
|
||||
|
||||
// statblock
|
||||
const $tblMon = $(`<table class="w-100 stats monster"/>`).appendTo(statTab.$wrpTab);
|
||||
const $tblMon = $(`<table class="w-100 stats monster"></table>`).appendTo(statTab.$wrpTab);
|
||||
RenderBestiary.$getRenderedCreature(this._state, {isSkipExcludesRender: true}).appendTo($tblMon);
|
||||
|
||||
// info
|
||||
const $tblInfo = $(`<table class="w-100 stats"/>`).appendTo(infoTab.$wrpTab);
|
||||
const $tblInfo = $(`<table class="w-100 stats"></table>`).appendTo(infoTab.$wrpTab);
|
||||
Renderer.utils.pBuildFluffTab({
|
||||
isImageTab: false,
|
||||
$content: $tblInfo,
|
||||
@@ -3493,7 +3498,7 @@ class CreatureBuilder extends Builder {
|
||||
});
|
||||
|
||||
// images
|
||||
const $tblImages = $(`<table class="w-100 stats"/>`).appendTo(imageTab.$wrpTab);
|
||||
const $tblImages = $(`<table class="w-100 stats"></table>`).appendTo(imageTab.$wrpTab);
|
||||
Renderer.utils.pBuildFluffTab({
|
||||
isImageTab: true,
|
||||
$content: $tblImages,
|
||||
@@ -3502,7 +3507,7 @@ class CreatureBuilder extends Builder {
|
||||
});
|
||||
|
||||
// data
|
||||
const $tblData = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"/>`).appendTo(dataTab.$wrpTab);
|
||||
const $tblData = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"></table>`).appendTo(dataTab.$wrpTab);
|
||||
const asJson = Renderer.get().render({
|
||||
type: "entries",
|
||||
entries: [
|
||||
@@ -3518,7 +3523,7 @@ class CreatureBuilder extends Builder {
|
||||
$tblData.append(Renderer.utils.getBorderTr());
|
||||
|
||||
// markdown
|
||||
const $tblMarkdown = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"/>`).appendTo(markdownTab.$wrpTab);
|
||||
const $tblMarkdown = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"></table>`).appendTo(markdownTab.$wrpTab);
|
||||
$tblMarkdown.append(Renderer.utils.getBorderTr());
|
||||
$tblMarkdown.append(`<tr><td colspan="6">${this._getRenderedMarkdownCode()}</td></tr>`);
|
||||
$tblMarkdown.append(Renderer.utils.getBorderTr());
|
||||
|
||||
@@ -157,11 +157,11 @@ class LegendaryGroupBuilder extends Builder {
|
||||
tabs.forEach(it => it.$wrpTab.appendTo($wrp));
|
||||
|
||||
// Legendary Group
|
||||
const $tblLegGroup = $(`<table class="w-100 stats"/>`).appendTo(legGroupTab.$wrpTab);
|
||||
const $tblLegGroup = $(`<table class="w-100 stats"></table>`).appendTo(legGroupTab.$wrpTab);
|
||||
RenderBestiary.$getRenderedLegendaryGroup(this._state).appendTo($tblLegGroup);
|
||||
|
||||
// Data
|
||||
const $tblData = $(`<table class="stats stats--book mkbru__wrp-output-tab-data"/>`).appendTo(dataTab.$wrpTab);
|
||||
const $tblData = $(`<table class="stats stats--book mkbru__wrp-output-tab-data"></table>`).appendTo(dataTab.$wrpTab);
|
||||
const asCode = Renderer.get().render({
|
||||
type: "entries",
|
||||
entries: [
|
||||
|
||||
@@ -319,10 +319,10 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const otherSourceRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
(this._state.otherSources || []).forEach(it => this.__$getOtherSourcesInput__getOtherSourceRow(doUpdateState, otherSourceRows, it).$wrp.appendTo($wrpRows));
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Other Source</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -355,7 +355,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getOtherSource};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows mkbru__wrp-rows--removable">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Source</span>${$selSource}</div>
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Page</span>${$iptPage}</div>
|
||||
@@ -378,10 +378,10 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const timeRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
this._state.time.forEach(time => SpellBuilder.__$getTimeInput__getTimeRow(doUpdateState, timeRows, time).$wrp.appendTo($wrpRows));
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Casting Time</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -430,7 +430,7 @@ class SpellBuilder extends Builder {
|
||||
<span class="mr-2 mkbru__sub-name--33">Condition</span>${$iptCond}
|
||||
</div>`.toggleVe(ixInitial === 2);
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows mkbru__wrp-rows--removable">
|
||||
<div class="ve-flex-v-center mb-2">${$iptNum}${$selUnit}</div>
|
||||
${$stageCond}
|
||||
@@ -646,10 +646,10 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const durationRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
this._state.duration.forEach(duration => SpellBuilder.__$getDurationInput__getDurationRow(doUpdateState, durationRows, duration).$wrp.appendTo($wrpRows));
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Duration</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -721,7 +721,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
// ENDS
|
||||
const endRows = [];
|
||||
const $wrpEndRows = $(`<div class="ve-flex-col"/>`);
|
||||
const $wrpEndRows = $(`<div class="ve-flex-col"></div>`);
|
||||
const $btnAddEnd = $(`<button class="btn btn-xs btn-default">Add "Until" Clause</button>`)
|
||||
.click(() => {
|
||||
SpellBuilder.__$getDurationInput__getDurationRow__getEndRow(doUpdateState, endRows, "dispel").$wrp.appendTo($wrpEndRows);
|
||||
@@ -735,7 +735,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getDuration};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows mkbru__wrp-rows--removable">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Duration Type</span>${$selDurationType}</div>
|
||||
${$stageAmount}
|
||||
@@ -761,7 +761,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getEnd};
|
||||
|
||||
const $wrpBtnRemove = $(`<div/>`);
|
||||
const $wrpBtnRemove = $(`<div></div>`);
|
||||
const $wrp = $$`<div class="ve-flex">
|
||||
<div class="mkbru__sub-name--33 mr-2"></div>
|
||||
<div class="mb-2 ve-flex-v-center w-100">${$selEndType}${$wrpBtnRemove}</div>
|
||||
@@ -792,7 +792,7 @@ class SpellBuilder extends Builder {
|
||||
};
|
||||
|
||||
// CLASSES
|
||||
const $wrpRowsCls = $(`<div/>`).appendTo($rowInnerCls);
|
||||
const $wrpRowsCls = $(`<div></div>`).appendTo($rowInnerCls);
|
||||
const doRefreshCls = () => {
|
||||
$wrpRowsCls.empty();
|
||||
classRows.splice(0, classRows.length);
|
||||
@@ -800,7 +800,7 @@ class SpellBuilder extends Builder {
|
||||
};
|
||||
doRefreshCls();
|
||||
|
||||
const $wrpBtnAddCls = $(`<div/>`).appendTo($rowInnerCls);
|
||||
const $wrpBtnAddCls = $(`<div></div>`).appendTo($rowInnerCls);
|
||||
$(`<button class="btn btn-xs btn-default">Add Class</button>`)
|
||||
.appendTo($wrpBtnAddCls)
|
||||
.click(() => {
|
||||
@@ -809,7 +809,7 @@ class SpellBuilder extends Builder {
|
||||
});
|
||||
|
||||
// SUBCLASSES
|
||||
const $wrpRowsSc = $(`<div/>`).appendTo($rowInnerSc);
|
||||
const $wrpRowsSc = $(`<div></div>`).appendTo($rowInnerSc);
|
||||
const doRefreshSc = () => {
|
||||
$wrpRowsSc.empty();
|
||||
subclassRows.splice(0, subclassRows.length);
|
||||
@@ -817,7 +817,7 @@ class SpellBuilder extends Builder {
|
||||
};
|
||||
doRefreshSc();
|
||||
|
||||
const $wrpBtnAddSc = $(`<div/>`).appendTo($rowInnerSc);
|
||||
const $wrpBtnAddSc = $(`<div></div>`).appendTo($rowInnerSc);
|
||||
$(`<button class="btn btn-xs btn-default">Add Subclass</button>`)
|
||||
.appendTo($wrpBtnAddSc)
|
||||
.click(() => {
|
||||
@@ -843,7 +843,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getClass};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows mkbru__wrp-rows--removable">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Class Name</span>${$iptClass}</div>
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Class Source</span>${$selClassSource}</div>
|
||||
@@ -897,7 +897,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getSubclass};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Class Name</span>${$iptClass}</div>
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Class Source</span>${$selClassSource}</div>
|
||||
@@ -926,7 +926,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const raceRows = [];
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
|
||||
const doRefresh = () => {
|
||||
$wrpRows.empty();
|
||||
@@ -935,7 +935,7 @@ class SpellBuilder extends Builder {
|
||||
};
|
||||
doRefresh();
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add Race</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -975,7 +975,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getRace};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Name</span>${$iptRace}</div>
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Source</span>${$selSource}</div>
|
||||
@@ -1042,7 +1042,7 @@ class SpellBuilder extends Builder {
|
||||
|
||||
const out = {getIdentObject};
|
||||
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"/>`);
|
||||
const $wrpBtnRemove = $(`<div class="text-right mb-2"></div>`);
|
||||
const $wrp = $$`<div class="ve-flex-col mkbru__wrp-rows">
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Name</span>${$iptName}</div>
|
||||
<div class="ve-flex-v-center mb-2"><span class="mr-2 mkbru__sub-name--33">Source</span>${$selSource}</div>
|
||||
@@ -1201,14 +1201,14 @@ class SpellBuilder extends Builder {
|
||||
tabs.forEach(it => it.$wrpTab.appendTo($wrp));
|
||||
|
||||
// Spell
|
||||
const $tblSpell = $(`<table class="w-100 stats"/>`).appendTo(spellTab.$wrpTab);
|
||||
const $tblSpell = $(`<table class="w-100 stats"></table>`).appendTo(spellTab.$wrpTab);
|
||||
// Make a copy of the spell, and add the data that would be displayed in the spells page
|
||||
const procSpell = MiscUtil.copy(this._state);
|
||||
Renderer.spell.initBrewSources(procSpell);
|
||||
RenderSpells.$getRenderedSpell(procSpell, this._subclassLookup, {isSkipExcludesRender: true}).appendTo($tblSpell);
|
||||
|
||||
// Info
|
||||
const $tblInfo = $(`<table class="w-100 stats"/>`).appendTo(infoTab.$wrpTab);
|
||||
const $tblInfo = $(`<table class="w-100 stats"></table>`).appendTo(infoTab.$wrpTab);
|
||||
Renderer.utils.pBuildFluffTab({
|
||||
isImageTab: false,
|
||||
$content: $tblInfo,
|
||||
@@ -1217,7 +1217,7 @@ class SpellBuilder extends Builder {
|
||||
});
|
||||
|
||||
// Images
|
||||
const $tblImages = $(`<table class="w-100 stats"/>`).appendTo(imageTab.$wrpTab);
|
||||
const $tblImages = $(`<table class="w-100 stats"></table>`).appendTo(imageTab.$wrpTab);
|
||||
Renderer.utils.pBuildFluffTab({
|
||||
isImageTab: true,
|
||||
$content: $tblImages,
|
||||
@@ -1226,7 +1226,7 @@ class SpellBuilder extends Builder {
|
||||
});
|
||||
|
||||
// Data
|
||||
const $tblData = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"/>`).appendTo(dataTab.$wrpTab);
|
||||
const $tblData = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"></table>`).appendTo(dataTab.$wrpTab);
|
||||
const asCode = Renderer.get().render({
|
||||
type: "entries",
|
||||
entries: [
|
||||
@@ -1242,7 +1242,7 @@ class SpellBuilder extends Builder {
|
||||
$tblData.append(Renderer.utils.getBorderTr());
|
||||
|
||||
// Markdown
|
||||
const $tblMarkdown = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"/>`).appendTo(markdownTab.$wrpTab);
|
||||
const $tblMarkdown = $(`<table class="w-100 stats stats--book mkbru__wrp-output-tab-data"></table>`).appendTo(markdownTab.$wrpTab);
|
||||
$tblMarkdown.append(Renderer.utils.getBorderTr());
|
||||
$tblMarkdown.append(`<tr><td colspan="6">${this._getRenderedMarkdownCode()}</td></tr>`);
|
||||
$tblMarkdown.append(Renderer.utils.getBorderTr());
|
||||
|
||||
@@ -247,7 +247,7 @@ class PageUi {
|
||||
$$`<div class="w-100">${$btnSourceAdd}</div>`.appendTo($mnu);
|
||||
|
||||
$mnu.append(PageUi.__$getSideMenuDivider(true));
|
||||
this._$menuInner = $(`<div/>`).appendTo($mnu);
|
||||
this._$menuInner = $(`<div></div>`).appendTo($mnu);
|
||||
|
||||
if (prevMode) await this._pSetActiveBuilder(prevMode);
|
||||
}
|
||||
@@ -453,7 +453,7 @@ class Builder extends ProxyBase {
|
||||
DataUtil.userDownloadText(`${DataUtil.getCleanFilename(BrewUtil2.sourceJsonToFull(this._ui.source))}.md`, mdOut);
|
||||
});
|
||||
|
||||
const $btnSettings = $(`<button class="btn btn-default btn-xs mb-2"><span class="glyphicon glyphicon-cog"/></button>`)
|
||||
const $btnSettings = $(`<button class="btn btn-default btn-xs mb-2"><span class="glyphicon glyphicon-cog"></span></button>`)
|
||||
.click(() => RendererMarkdown.pShowSettingsModal());
|
||||
|
||||
return $$`<div class="ve-flex-v-center btn-group">${$btnDownload}${$btnSettings}</div>`;
|
||||
@@ -520,7 +520,7 @@ class Builder extends ProxyBase {
|
||||
return;
|
||||
}
|
||||
|
||||
const $btnEdit = $(`<button class="btn btn-xs btn-default mr-2" title="Edit"><span class="glyphicon glyphicon-pencil"/></button>`)
|
||||
const $btnEdit = $(`<button class="btn btn-xs btn-default mr-2" title="Edit"><span class="glyphicon glyphicon-pencil"></span></button>`)
|
||||
.click(async () => {
|
||||
if (
|
||||
this.getOnNavMessage()
|
||||
@@ -616,10 +616,10 @@ class Builder extends ProxyBase {
|
||||
),
|
||||
]);
|
||||
|
||||
const $btnBurger = $(`<button class="btn btn-xs btn-default mr-2" title="More Options"><span class="glyphicon glyphicon-option-vertical"/></button>`)
|
||||
const $btnBurger = $(`<button class="btn btn-xs btn-default mr-2" title="More Options"><span class="glyphicon glyphicon-option-vertical"></span></button>`)
|
||||
.click(evt => ContextUtil.pOpenMenu(evt, menu));
|
||||
|
||||
const $btnDelete = $(`<button class="btn btn-xs btn-danger" title="Delete"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnDelete = $(`<button class="btn btn-xs btn-danger" title="Delete"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Delete Entity", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
|
||||
@@ -772,7 +772,7 @@ class Builder extends ProxyBase {
|
||||
static $getBtnRemoveRow (doUpdateState, rowArr, row, $wrpRow, title, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
return $(`<button class="btn ${opts.isExtraSmall ? "btn-xxs" : "btn-xs"} btn-danger ${opts.isProtectLast ? "mkbru__btn-rm-row" : ""}" title="Remove ${title}"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
return $(`<button class="btn ${opts.isExtraSmall ? "btn-xxs" : "btn-xs"} btn-danger ${opts.isProtectLast ? "mkbru__btn-rm-row" : ""}" title="Remove ${title}"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
rowArr.splice(rowArr.indexOf(row), 1);
|
||||
$wrpRow.empty().remove();
|
||||
@@ -806,12 +806,12 @@ class Builder extends ProxyBase {
|
||||
doUpdateState();
|
||||
};
|
||||
|
||||
const $wrpRowsOuter = $(`<div class="relative"/>`);
|
||||
const $wrpRows = $(`<div class="ve-flex-col"/>`).appendTo($wrpRowsOuter);
|
||||
const $wrpRowsOuter = $(`<div class="relative"></div>`);
|
||||
const $wrpRows = $(`<div class="ve-flex-col"></div>`).appendTo($wrpRowsOuter);
|
||||
|
||||
const rowOptions = {$wrpRowsOuter};
|
||||
|
||||
const $iptEntries = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2"/>`)
|
||||
const $iptEntries = $(`<textarea class="form-control form-control--minimal resize-vertical mb-2"></textarea>`)
|
||||
.change(() => doUpdateState());
|
||||
|
||||
const $btnAddImage = $(`<button class="btn btn-xs btn-default">Add Image</button>`)
|
||||
@@ -854,7 +854,7 @@ class Builder extends ProxyBase {
|
||||
}
|
||||
}
|
||||
|
||||
const $btnPreview = $(`<button class="btn btn-xs btn-default mr-2" title="Preview Image"><span class="glyphicon glyphicon-fullscreen"/></button>`)
|
||||
const $btnPreview = $(`<button class="btn btn-xs btn-default mr-2" title="Preview Image"><span class="glyphicon glyphicon-fullscreen"></span></button>`)
|
||||
.click((evt) => {
|
||||
const toRender = getState();
|
||||
if (!toRender) return JqueryUtil.doToast({content: "Please enter an image URL", type: "warning"});
|
||||
@@ -871,7 +871,7 @@ class Builder extends ProxyBase {
|
||||
);
|
||||
});
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Image"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Image"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
imageRows.splice(imageRows.indexOf(out), 1);
|
||||
out.$ele.empty().remove();
|
||||
@@ -978,8 +978,8 @@ class BuilderUi {
|
||||
|
||||
const eleType = options.eleType || "div";
|
||||
|
||||
const $rowInner = $(`<div class="${options.isRow ? "ve-flex" : "ve-flex-col"} w-100"/>`);
|
||||
const $row = $$`<div class="mb-2 mkbru__row stripe-even"><${eleType} class="mkbru__wrp-row ve-flex-v-center"><span class="mr-2 mkbru__row-name ve-shrink-10 ${options.isMarked ? `mkbru__row-name--marked` : ""} ${options.title ? "help" : ""}" ${options.title ? `title="${options.title}"` : ""}>${name}</span>${options.isMarked ? `<div class="mkbru__row-mark mr-2"/>` : ""}${$rowInner}</${eleType}></div>`;
|
||||
const $rowInner = $(`<div class="${options.isRow ? "ve-flex" : "ve-flex-col"} w-100"></div>`);
|
||||
const $row = $$`<div class="mb-2 mkbru__row stripe-even"><${eleType} class="mkbru__wrp-row ve-flex-v-center"><span class="mr-2 mkbru__row-name ve-shrink-10 ${options.isMarked ? `mkbru__row-name--marked` : ""} ${options.title ? "help" : ""}" ${options.title ? `title="${options.title}"` : ""}>${name}</span>${options.isMarked ? `<div class="mkbru__row-mark mr-2"></div>` : ""}${$rowInner}</${eleType}></div>`;
|
||||
return [$row, $rowInner];
|
||||
}
|
||||
|
||||
@@ -1067,10 +1067,10 @@ class BuilderUi {
|
||||
fnRender();
|
||||
};
|
||||
|
||||
const $wrpRows = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpRows = $(`<div></div>`).appendTo($rowInner);
|
||||
initialState.forEach(string => BuilderUi._$getStateIptStringArray_getRow(doUpdateState, stringRows, string).$wrp.appendTo($wrpRows));
|
||||
|
||||
const $wrpBtnAdd = $(`<div/>`).appendTo($rowInner);
|
||||
const $wrpBtnAdd = $(`<div></div>`).appendTo($rowInner);
|
||||
$(`<button class="btn btn-xs btn-default">Add ${options.shortName}</button>`)
|
||||
.appendTo($wrpBtnAdd)
|
||||
.click(() => {
|
||||
@@ -1095,7 +1095,7 @@ class BuilderUi {
|
||||
.change(() => doUpdateState());
|
||||
if (initialString && initialString.trim()) $iptString.val(initialString);
|
||||
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnRemove = $(`<button class="btn btn-xs btn-danger" title="Remove Row"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
stringRows.splice(stringRows.indexOf(out), 1);
|
||||
$wrp.empty().remove();
|
||||
@@ -1183,7 +1183,7 @@ class BuilderUi {
|
||||
const [$row, $rowInner] = BuilderUi.getLabelledRowTuple(name, {isMarked: true});
|
||||
|
||||
const initialState = MiscUtil.get(state, ...path) || [];
|
||||
const $wrpIpts = $(`<div class="ve-flex-col w-100 mr-2"/>`).appendTo($rowInner);
|
||||
const $wrpIpts = $(`<div class="ve-flex-col w-100 mr-2"></div>`).appendTo($rowInner);
|
||||
const inputs = [];
|
||||
options.vals.forEach(val => {
|
||||
const $cb = $(`<input class="mkbru__ipt-cb" type="checkbox">`)
|
||||
@@ -1239,7 +1239,7 @@ class BuilderUi {
|
||||
}
|
||||
|
||||
static $getUpButton (cbUpdate, rows, myRow) {
|
||||
return $(`<button class="btn btn-xs btn-default mkbru__btn-up-row ml-2" title="Move Up"><span class="glyphicon glyphicon-arrow-up"/></button>`)
|
||||
return $(`<button class="btn btn-xs btn-default mkbru__btn-up-row ml-2" title="Move Up"><span class="glyphicon glyphicon-arrow-up"></span></button>`)
|
||||
.click(() => {
|
||||
const ix = rows.indexOf(myRow);
|
||||
const cache = rows[ix - 1];
|
||||
@@ -1250,7 +1250,7 @@ class BuilderUi {
|
||||
}
|
||||
|
||||
static $getDownButton (cbUpdate, rows, myRow) {
|
||||
return $(`<button class="btn btn-xs btn-default mkbru__btn-down-row ml-2" title="Move Down"><span class="glyphicon glyphicon-arrow-down"/></button>`)
|
||||
return $(`<button class="btn btn-xs btn-default mkbru__btn-down-row ml-2" title="Move Down"><span class="glyphicon glyphicon-arrow-down"></span></button>`)
|
||||
.click(() => {
|
||||
const ix = rows.indexOf(myRow);
|
||||
const cache = rows[ix + 1];
|
||||
@@ -1278,14 +1278,14 @@ class BuilderUi {
|
||||
});
|
||||
|
||||
dragMeta.on = true;
|
||||
dragMeta.$wrap = $(`<div class="ve-flex-col ui-drag__wrp-drag-block"/>`).appendTo(options.$wrpRowsOuter);
|
||||
dragMeta.$wrap = $(`<div class="ve-flex-col ui-drag__wrp-drag-block"></div>`).appendTo(options.$wrpRowsOuter);
|
||||
dragMeta.$dummies = [];
|
||||
|
||||
const ixRow = rows.indexOf(myRow);
|
||||
|
||||
rows.forEach((row, i) => {
|
||||
const dimensions = {w: row.$ele.outerWidth(true), h: row.$ele.outerHeight(true)};
|
||||
const $dummy = $(`<div class="${i === ixRow ? "ui-drag__wrp-drag-dummy--highlight" : "ui-drag__wrp-drag-dummy--lowlight"}"/>`)
|
||||
const $dummy = $(`<div class="${i === ixRow ? "ui-drag__wrp-drag-dummy--highlight" : "ui-drag__wrp-drag-dummy--lowlight"}"></div>`)
|
||||
.width(dimensions.w).height(dimensions.h)
|
||||
.mouseup(() => {
|
||||
if (dragMeta.on) {
|
||||
|
||||
@@ -74,7 +74,7 @@ class MakeCards extends BaseComponent {
|
||||
const kColor = `color_${entityType}`;
|
||||
const kIcon = `icon_${entityType}`;
|
||||
const $iptColor = ComponentUiUtil.$getIptColor(this, kColor).addClass("cards-cfg__ipt-color");
|
||||
const $dispIcon = $(`<div class="cards__disp-btn-icon"/>`);
|
||||
const $dispIcon = $(`<div class="cards__disp-btn-icon"></div>`);
|
||||
const $btnChooseIcon = $$`<button class="btn btn-xs btn-default cards__btn-choose-icon">${$dispIcon}</button>`
|
||||
.click(async () => {
|
||||
const icon = await MakeCards._pGetUserIcon(this._state[kIcon]);
|
||||
@@ -101,16 +101,16 @@ class MakeCards extends BaseComponent {
|
||||
const menuSearch = ContextUtil.getMenu(this._render_getContextMenuOptions());
|
||||
|
||||
const $iptSearch = $(`<input type="search" class="form-control mr-2" placeholder="Search cards...">`);
|
||||
const $btnAdd = $(`<button class="btn btn-primary mr-2"><span class="glyphicon glyphicon-plus"/> Add</button>`)
|
||||
const $btnAdd = $(`<button class="btn btn-primary mr-2"><span class="glyphicon glyphicon-plus"></span> Add</button>`)
|
||||
.click(evt => ContextUtil.pOpenMenu(evt, menuSearch));
|
||||
const $btnReset = $(`<button class="btn btn-danger mr-2"><span class="glyphicon glyphicon-trash"/> Reset</button>`)
|
||||
.click(() => {
|
||||
if (!confirm("Are you sure?")) return;
|
||||
const $btnReset = $(`<button class="btn btn-danger mr-2"><span class="glyphicon glyphicon-trash"></span> Reset</button>`)
|
||||
.click(async () => {
|
||||
if (!await InputUiUtil.pGetUserBoolean({title: "Reset", htmlDescription: "Are you sure?", textYes: "Yes", textNo: "Cancel"})) return;
|
||||
this._list.removeAllItems();
|
||||
this._list.update();
|
||||
this._doSaveStateDebounced();
|
||||
});
|
||||
const $btnExport = $(`<button class="btn btn-default"><span class="glyphicon glyphicon-download"/> Export JSON</button>`)
|
||||
const $btnExport = $(`<button class="btn btn-default"><span class="glyphicon glyphicon-download"></span> Export JSON</button>`)
|
||||
.click(() => {
|
||||
const toDownload = this._list.items.map(it => {
|
||||
const entityMeta = MakeCards._AVAILABLE_TYPES[it.values.entityType];
|
||||
@@ -190,10 +190,10 @@ class MakeCards extends BaseComponent {
|
||||
<div class="ve-col-1-1 mr-2 ve-flex-vh-center">Color</div>
|
||||
<div class="ve-col-1-1 mr-2 ve-flex-vh-center">Icon</div>
|
||||
<div class="ve-col-1 mr-2 ve-flex-vh-center">Count</div>
|
||||
<div class="ve-col-1-1 ve-flex-v-center ve-flex-h-right"/>
|
||||
<div class="ve-col-1-1 ve-flex-v-center ve-flex-h-right"></div>
|
||||
</div>`.appendTo($wrpContainer);
|
||||
|
||||
const $wrpList = $(`<div class="w-100 h-100"/>`);
|
||||
const $wrpList = $(`<div class="w-100 h-100"></div>`);
|
||||
$$`<div class="ve-flex-col h-100 w-100 ve-overflow-y-auto mt-2 ve-overflow-x-hidden">${$wrpList}</div>`.appendTo($wrpContainer);
|
||||
|
||||
this._list = new List({$iptSearch, $wrpList, isUseJquery: true});
|
||||
@@ -319,7 +319,7 @@ class MakeCards extends BaseComponent {
|
||||
this._doSaveStateDebounced();
|
||||
};
|
||||
|
||||
const $dispIcon = $(`<div class="cards__disp-btn-icon"/>`)
|
||||
const $dispIcon = $(`<div class="cards__disp-btn-icon"></div>`)
|
||||
.css("background-image", `url('${MakeCards._getIconPath(cardMeta.icon)}')`);
|
||||
const $btnIcon = $$`<button class="btn btn-default btn-xs cards__btn-choose-icon">${$dispIcon}</button>`
|
||||
.click(async () => {
|
||||
@@ -341,7 +341,7 @@ class MakeCards extends BaseComponent {
|
||||
})
|
||||
.val(cardMeta.count);
|
||||
|
||||
const $btnCopy = $(`<button class="btn btn-default btn-xs mr-2" title="Copy JSON (SHIFT to view JSON)"><span class="glyphicon glyphicon-copy"/></button>`)
|
||||
const $btnCopy = $(`<button class="btn btn-default btn-xs mr-2" title="Copy JSON (SHIFT to view JSON)"><span class="glyphicon glyphicon-copy"></span></button>`)
|
||||
.click(async evt => {
|
||||
const entityMeta = MakeCards._AVAILABLE_TYPES[listItem.values.entityType];
|
||||
const toCopy = {
|
||||
@@ -371,7 +371,7 @@ class MakeCards extends BaseComponent {
|
||||
JqueryUtil.showCopiedEffect($btnCopy, "Copied JSON!");
|
||||
}
|
||||
});
|
||||
const $btnDelete = $(`<button class="btn btn-danger btn-xs" title="Remove"><span class="glyphicon glyphicon-trash"/></button>`)
|
||||
const $btnDelete = $(`<button class="btn btn-danger btn-xs" title="Remove"><span class="glyphicon glyphicon-trash"></span></button>`)
|
||||
.click(() => {
|
||||
this._list.removeItemByIndex(uid);
|
||||
this._list.update();
|
||||
@@ -631,7 +631,7 @@ class MakeCards extends BaseComponent {
|
||||
source: icon_names,
|
||||
items: "16",
|
||||
fnGetItemPrefix: (iconName) => {
|
||||
return `<span class="cards__disp-typeahead-icon mr-2" style="background-image: url('${MakeCards._getIconPath(iconName)}')"/> `;
|
||||
return `<span class="cards__disp-typeahead-icon mr-2" style="background-image: url('${MakeCards._getIconPath(iconName)}')"></span> `;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class ManageBrew {
|
||||
|
||||
static async pRender () {
|
||||
const manager = new ManageBrewUi({brewUtil: BrewUtil2});
|
||||
return manager.pRender($(`#brewmanager`).empty());
|
||||
return manager.pRender($(`#manager`).empty());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class ManagePrerelease {
|
||||
|
||||
static async pRender () {
|
||||
const manager = new ManageBrewUi({brewUtil: PrereleaseUtil});
|
||||
return manager.pRender($(`#prereleasemanager`).empty());
|
||||
return manager.pRender($(`#manager`).empty());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -272,7 +272,13 @@ class MapsPage extends BaseComponent {
|
||||
}
|
||||
|
||||
_getSearchName ({sourceMeta}) {
|
||||
return this._getTitleName({sourceMeta}).toLowerCase().trim();
|
||||
return [
|
||||
this._getTitleName({sourceMeta}),
|
||||
Parser.sourceJsonToAbv(sourceMeta.source),
|
||||
]
|
||||
.join(" - ")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
}
|
||||
|
||||
_isVisibleSourceSearch ({searchName}) { return searchName.includes(this._state.search.trim().toLowerCase()); }
|
||||
|
||||
@@ -15,7 +15,7 @@ class NavBar {
|
||||
|
||||
static _onLoad () {
|
||||
NavBar._dropdowns = [...NavBar._navbar.querySelectorAll(`li.dropdown--navbar`)];
|
||||
document.addEventListener("click", () => NavBar._dropdowns.forEach(ele => ele.classList.remove("open")));
|
||||
document.addEventListener("click", () => NavBar._closeAllDropdowns());
|
||||
|
||||
NavBar._clearAllTimers();
|
||||
|
||||
@@ -123,19 +123,11 @@ class NavBar {
|
||||
this._addElement_button(
|
||||
NavBar._CAT_SETTINGS,
|
||||
{
|
||||
html: styleSwitcher.getDayNightButtonText(),
|
||||
click: (evt) => NavBar.InteractionManager._onClick_button_dayNight(evt),
|
||||
context: (evt) => NavBar.InteractionManager._onContext_button_dayNight(evt),
|
||||
className: "nightModeToggle",
|
||||
},
|
||||
);
|
||||
this._addElement_button(
|
||||
NavBar._CAT_SETTINGS,
|
||||
{
|
||||
html: styleSwitcher.getActiveWide() === true ? "Disable Wide Mode" : "Enable Wide Mode (Experimental)",
|
||||
click: (evt) => NavBar.InteractionManager._onClick_button_wideMode(evt),
|
||||
className: "wideModeToggle",
|
||||
title: "This feature is unsupported. Expect bugs.",
|
||||
html: "Preferences",
|
||||
click: () => {
|
||||
ConfigUi.show();
|
||||
NavBar._closeAllDropdowns();
|
||||
},
|
||||
},
|
||||
);
|
||||
this._addElement_divider(NavBar._CAT_SETTINGS);
|
||||
@@ -395,7 +387,7 @@ class NavBar {
|
||||
a.setAttribute("target", "_blank");
|
||||
a.classList.add("inline-split-v-center");
|
||||
a.classList.add("w-100");
|
||||
a.innerHTML = `<span>${aText}</span><span class="glyphicon glyphicon-new-window"/>`;
|
||||
a.innerHTML = `<span>${aText}</span><span class="glyphicon glyphicon-new-window"></span>`;
|
||||
}
|
||||
|
||||
li.appendChild(a);
|
||||
@@ -618,6 +610,10 @@ class NavBar {
|
||||
else NavBar._openDropdown(ele);
|
||||
}
|
||||
|
||||
static _closeAllDropdowns () {
|
||||
NavBar._dropdowns.forEach(ele => ele.classList.remove("open"));
|
||||
}
|
||||
|
||||
static _openDropdown (ele) {
|
||||
const lisOpen = [];
|
||||
|
||||
|
||||
@@ -644,7 +644,7 @@ class Omnisearch {
|
||||
|
||||
static addScrollTopFloat () {
|
||||
// "To top" button
|
||||
const $btnToTop = $(`<button class="btn btn-sm btn-default" title="To Top"><span class="glyphicon glyphicon-arrow-up"/></button>`)
|
||||
const $btnToTop = $(`<button class="btn btn-sm btn-default" title="To Top"><span class="glyphicon glyphicon-arrow-up"></span></button>`)
|
||||
.click(() => MiscUtil.scrollPageTop());
|
||||
|
||||
const $wrpTop = $$`<div class="bk__to-top no-print">
|
||||
|
||||
@@ -1683,6 +1683,8 @@ Parser.monSpellcastingTagToFull = function (tag) {
|
||||
|
||||
Parser.MON_MISC_TAG_TO_FULL = {
|
||||
"AOE": "Has Areas of Effect",
|
||||
"CUR": "Inflicts Curse",
|
||||
"DIS": "Inflicts Disease",
|
||||
"HPR": "Has HP Reduction",
|
||||
"MW": "Has Weapon Attacks, Melee",
|
||||
"RW": "Has Weapon Attacks, Ranged",
|
||||
|
||||
7
js/privacy-policy.js
Normal file
7
js/privacy-policy.js
Normal file
@@ -0,0 +1,7 @@
|
||||
window.addEventListener("load", async () => {
|
||||
await Promise.all([
|
||||
PrereleaseUtil.pInit(),
|
||||
BrewUtil2.pInit(),
|
||||
]);
|
||||
ExcludeUtil.pInitialise().then(null); // don't await, as this is only used for search
|
||||
});
|
||||
@@ -48,7 +48,7 @@ class RenderDeities {
|
||||
|
||||
${entriesMeta.entriesAttributes.map(entry => `<tr><td colspan="6">${Renderer.get().render(entry)}</td></tr>`).join("")}
|
||||
|
||||
${deity.symbolImg ? `<tr><td colspan="6">${renderer.render({entries: [deity.symbolImg]})}<div class="mb-2"/></td></tr>` : ""}
|
||||
${deity.symbolImg ? `<tr><td colspan="6">${renderer.render({entries: [deity.symbolImg]})}<div class="mb-2"></div></td></tr>` : ""}
|
||||
${renderStack.length ? `<tr class="text"><td class="pt-2" colspan="6">${renderStack.join("")}</td></tr>` : ""}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ class RenderItems {
|
||||
<td class="text-right" colspan="4">${textRight}</td>
|
||||
</tr>` : `<tr><td colspan="6" class="${textRight ? "text-right" : ""}">${textLeft || textRight}</td></tr>`}
|
||||
|
||||
${renderedText ? `<tr><td class="divider" colspan="6"><div/></td></tr>
|
||||
${renderedText ? `<tr><td class="divider" colspan="6"><div></div></td></tr>
|
||||
<tr class="text"><td colspan="6">${renderedText}</td></tr>` : ""}
|
||||
${Renderer.utils.getPageTr(item, {tag: "item", fnUnpackUid: (uid) => DataUtil.proxy.unpackUid("item", uid, "item")})}
|
||||
${Renderer.utils.getBorderTr()}
|
||||
|
||||
@@ -132,7 +132,7 @@ class RenderMap {
|
||||
const X = 0;
|
||||
const Y = 1;
|
||||
|
||||
const $cvs = $(`<canvas class="p-0 m-0"/>`);
|
||||
const $cvs = $(`<canvas class="p-0 m-0"></canvas>`);
|
||||
const cvs = $cvs[0];
|
||||
cvs.width = mapData.width;
|
||||
cvs.height = mapData.height;
|
||||
@@ -345,16 +345,16 @@ class RenderMap {
|
||||
});
|
||||
});
|
||||
|
||||
const $btnZoomMinus = $(`<button class="btn btn-xs btn-default"><span class="glyphicon glyphicon-zoom-out"/> Zoom Out</button>`)
|
||||
const $btnZoomMinus = $(`<button class="btn btn-xs btn-default"><span class="glyphicon glyphicon-zoom-out"></span> Zoom Out</button>`)
|
||||
.click(() => zoomChange("out"));
|
||||
|
||||
const $btnZoomPlus = $(`<button class="btn btn-xs btn-default"><span class="glyphicon glyphicon-zoom-in"/> Zoom In</button>`)
|
||||
const $btnZoomPlus = $(`<button class="btn btn-xs btn-default"><span class="glyphicon glyphicon-zoom-in"></span> Zoom In</button>`)
|
||||
.click(() => zoomChange("in"));
|
||||
|
||||
const $btnZoomReset = $(`<button class="btn btn-xs btn-default" title="Reset Zoom"><span class="glyphicon glyphicon-search"/> Reset Zoom</button>`)
|
||||
const $btnZoomReset = $(`<button class="btn btn-xs btn-default" title="Reset Zoom"><span class="glyphicon glyphicon-search"></span> Reset Zoom</button>`)
|
||||
.click(() => zoomChange("reset"));
|
||||
|
||||
const $btnHelp = $(`<button class="btn btn-xs btn-default ml-auto mr-4" title="Help"><span class="glyphicon glyphicon-info-sign"/> Help</button>`)
|
||||
const $btnHelp = $(`<button class="btn btn-xs btn-default ml-auto mr-4" title="Help"><span class="glyphicon glyphicon-info-sign"></span> Help</button>`)
|
||||
.click(evt => {
|
||||
const {$modalInner} = UiUtil.getShowModal({
|
||||
title: "Help",
|
||||
|
||||
@@ -2,15 +2,7 @@
|
||||
|
||||
// TODO implement remaining methods
|
||||
class RendererMarkdown {
|
||||
static async pInit () {
|
||||
const settings = await StorageUtil.pGet("bookViewSettingsMarkdown") || Object.entries(RendererMarkdown._CONFIG).mergeMap(([k, v]) => ({[k]: v.default}));
|
||||
Object.assign(RendererMarkdown, settings);
|
||||
RendererMarkdown._isInit = true;
|
||||
}
|
||||
|
||||
static checkInit () {
|
||||
if (!RendererMarkdown._isInit) throw new Error(`RendererMarkdown has not been initialised!`);
|
||||
}
|
||||
static CHARS_PER_PAGE = 5500;
|
||||
|
||||
getLineBreak () { return "\n"; }
|
||||
|
||||
@@ -34,8 +26,6 @@ class RendererMarkdown {
|
||||
set isSkipStylingItemLinks (val) { this._isSkipStylingItemLinks = val; }
|
||||
|
||||
static get () {
|
||||
RendererMarkdown.checkInit();
|
||||
|
||||
return new RendererMarkdown().setFnPostProcess(RendererMarkdown._fnPostProcess);
|
||||
}
|
||||
|
||||
@@ -639,26 +629,23 @@ class RendererMarkdown {
|
||||
|
||||
// region primitives
|
||||
_renderString (entry, textStack, meta, options) {
|
||||
switch (RendererMarkdown._tagRenderMode || 0) {
|
||||
// render tags where possible
|
||||
case 0: {
|
||||
this._renderString_renderMode0(entry, textStack, meta, options);
|
||||
switch (VetoolsConfig.get("markdown", "tagRenderMode") || "convertMarkdown") {
|
||||
case "convertMarkdown": {
|
||||
this._renderString_renderModeConvertMarkdown(entry, textStack, meta, options);
|
||||
break;
|
||||
}
|
||||
// leave tags as-is
|
||||
case 1: {
|
||||
case "ignore": {
|
||||
textStack[0] += entry;
|
||||
break;
|
||||
}
|
||||
// strip tags
|
||||
case 2: {
|
||||
case "convertText": {
|
||||
textStack[0] += Renderer.stripTags(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_renderString_renderMode0 (entry, textStack, meta, options) {
|
||||
_renderString_renderModeConvertMarkdown (entry, textStack, meta, options) {
|
||||
const tagSplit = Renderer.splitByTags(entry);
|
||||
const len = tagSplit.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
@@ -786,64 +773,10 @@ class RendererMarkdown {
|
||||
|
||||
// region Static options
|
||||
static async pShowSettingsModal () {
|
||||
RendererMarkdown.checkInit();
|
||||
|
||||
const {$modalInner} = UiUtil.getShowModal({
|
||||
title: "Markdown Settings",
|
||||
cbClose: () => RendererMarkdown.__$wrpSettings.detach(),
|
||||
});
|
||||
if (!RendererMarkdown.__$wrpSettings) {
|
||||
const _compMarkdownSettings = BaseComponent.fromObject({
|
||||
_tagRenderMode: RendererMarkdown._tagRenderMode,
|
||||
_isAddColumnBreaks: RendererMarkdown._isAddColumnBreaks,
|
||||
});
|
||||
const compMarkdownSettings = _compMarkdownSettings.getPod();
|
||||
const saveMarkdownSettingsDebounced = MiscUtil.debounce(() => StorageUtil.pSet("bookViewSettingsMarkdown", _compMarkdownSettings.toObject()), 100);
|
||||
compMarkdownSettings.addHookAll(() => {
|
||||
Object.assign(RendererMarkdown, compMarkdownSettings.getState());
|
||||
saveMarkdownSettingsDebounced();
|
||||
});
|
||||
|
||||
const $rows = Object.entries(RendererMarkdown._CONFIG)
|
||||
.map(([k, v]) => {
|
||||
let $ipt;
|
||||
switch (v.type) {
|
||||
case "boolean": {
|
||||
$ipt = ComponentUiUtil.$getCbBool(_compMarkdownSettings, k).addClass("mr-1");
|
||||
break;
|
||||
}
|
||||
case "enum": {
|
||||
$ipt = ComponentUiUtil.$getSelEnum(_compMarkdownSettings, k, {values: v.values, fnDisplay: v.fnDisplay});
|
||||
break;
|
||||
}
|
||||
default: throw new Error(`Unhandled input type!`);
|
||||
}
|
||||
|
||||
return $$`<div class="m-1 stripe-even"><label class="split-v-center">
|
||||
<div class="w-100 mr-2">${v.name}</div>
|
||||
${$ipt.addClass("max-w-33")}
|
||||
</label></div>`;
|
||||
});
|
||||
|
||||
RendererMarkdown.__$wrpSettings = $$`<div class="ve-flex-v-col w-100 h-100">${$rows}</div>`;
|
||||
}
|
||||
RendererMarkdown.__$wrpSettings.appendTo($modalInner);
|
||||
ConfigUi.show({settingsGroupIds: ["markdown"]});
|
||||
}
|
||||
// endregion
|
||||
|
||||
static getSetting (key) { return this[`_${key}`]; }
|
||||
}
|
||||
RendererMarkdown._isInit = false;
|
||||
RendererMarkdown.CHARS_PER_PAGE = 5500;
|
||||
RendererMarkdown.__$wrpSettings = null;
|
||||
RendererMarkdown._TAG_RENDER_MODES = ["Convert to Markdown", "Leave As-Is", "Convert to Text"];
|
||||
RendererMarkdown._CONFIG = {
|
||||
_tagRenderMode: {default: 0, name: "Tag Handling (<code>@tag</code>)", fnDisplay: ix => RendererMarkdown._TAG_RENDER_MODES[ix], type: "enum", values: [0, 1, 2]},
|
||||
_isAddColumnBreaks: {default: false, name: "Add GM Binder Column Breaks (<code>\\columnbreak</code>)", type: "boolean"},
|
||||
_isAddPageBreaks: {default: false, name: "Add GM Binder Page Breaks (<code>\\pagebreak</code>)", type: "boolean"},
|
||||
};
|
||||
|
||||
if (typeof window !== "undefined") window.addEventListener("load", () => RendererMarkdown.pInit());
|
||||
|
||||
RendererMarkdown.utils = class {
|
||||
static getPageText (it) {
|
||||
@@ -964,7 +897,7 @@ ${mon.pbNote || Parser.crToNumber(mon.cr) < VeCt.CR_CUSTOM ? `>- **Proficiency B
|
||||
|
||||
let breakablePart = `${traitsPart}${actionsPart}${bonusActionsPart}${reactionsPart}${legendaryActionsPart}${mythicActionsPart}${legendaryGroupLairPart}${legendaryGroupRegionalPart}${footerPart}`;
|
||||
|
||||
if (RendererMarkdown.getSetting("isAddColumnBreaks")) {
|
||||
if (VetoolsConfig.get("markdown", "isAddColumnBreaks")) {
|
||||
let charAllowanceFirstCol = 2200 - unbreakablePart.length;
|
||||
|
||||
const breakableLines = breakablePart.split("\n");
|
||||
@@ -1102,7 +1035,7 @@ ${mon.pbNote || Parser.crToNumber(mon.cr) < VeCt.CR_CUSTOM ? `>- **Proficiency B
|
||||
|
||||
const out = [monEntry];
|
||||
|
||||
const isAddPageBreaks = RendererMarkdown.getSetting("isAddPageBreaks");
|
||||
const isAddPageBreaks = VetoolsConfig.get("markdown", "isAddPageBreaks");
|
||||
if (fluffText) {
|
||||
// Insert a page break before every fluff section
|
||||
if (isAddPageBreaks) out.push("", "\\pagebreak", "");
|
||||
|
||||
102
js/render.js
102
js/render.js
@@ -3143,21 +3143,29 @@ Renderer.utils = class {
|
||||
return fluff;
|
||||
}
|
||||
|
||||
static async _pGetFluff ({entity, fluffProp} = {}) {
|
||||
const fluffEntity = await DataLoader.pCacheAndGet(fluffProp, entity.source, UrlUtil.URL_TO_HASH_BUILDER[fluffProp](entity));
|
||||
static async _pGetFluff ({entity, fluffProp, lockToken2} = {}) {
|
||||
const fluffEntity = await DataLoader.pCacheAndGet(fluffProp, entity.source, UrlUtil.URL_TO_HASH_BUILDER[fluffProp](entity), {lockToken2});
|
||||
if (fluffEntity) return fluffEntity;
|
||||
|
||||
if (entity._versionBase_name && entity._versionBase_source) {
|
||||
return DataLoader.pCacheAndGet(fluffProp, entity.source, UrlUtil.URL_TO_HASH_BUILDER[fluffProp]({
|
||||
name: entity._versionBase_name,
|
||||
source: entity._versionBase_source,
|
||||
}));
|
||||
return DataLoader.pCacheAndGet(
|
||||
fluffProp,
|
||||
entity.source,
|
||||
UrlUtil.URL_TO_HASH_BUILDER[fluffProp]({
|
||||
name: entity._versionBase_name,
|
||||
source: entity._versionBase_source,
|
||||
}),
|
||||
{
|
||||
lockToken2,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async pGetFluff ({entity, pFnPostProcess, fluffProp} = {}) {
|
||||
// TODO(Future) move into `DataLoader`; cleanup `lockToken2` usage
|
||||
static async pGetFluff ({entity, pFnPostProcess, fluffProp, lockToken2 = null} = {}) {
|
||||
const predefinedFluff = await Renderer.utils.pGetPredefinedFluff(entity, fluffProp);
|
||||
if (predefinedFluff) {
|
||||
if (pFnPostProcess) return pFnPostProcess(predefinedFluff);
|
||||
@@ -6430,16 +6438,16 @@ Renderer.race = class {
|
||||
opts = opts || {};
|
||||
|
||||
const out = [];
|
||||
races.forEach(r => {
|
||||
races.forEach(race => {
|
||||
// FIXME(Deprecated) Backwards compatibility for old race data; remove at some point
|
||||
if (r.size && typeof r.size === "string") r.size = [r.size];
|
||||
if (race.size && typeof race.size === "string") race.size = [race.size];
|
||||
|
||||
// Ignore `"lineage": true`, as it is only used for filters
|
||||
if (r.lineage && r.lineage !== true) {
|
||||
r = MiscUtil.copyFast(r);
|
||||
if (race.lineage && race.lineage !== true) {
|
||||
race = MiscUtil.copyFast(race);
|
||||
|
||||
if (r.lineage === "VRGR") {
|
||||
r.ability = r.ability || [
|
||||
if (race.lineage === "VRGR") {
|
||||
race.ability = race.ability || [
|
||||
{
|
||||
choose: {
|
||||
weighted: {
|
||||
@@ -6457,8 +6465,8 @@ Renderer.race = class {
|
||||
},
|
||||
},
|
||||
];
|
||||
} else if (r.lineage === "UA1") {
|
||||
r.ability = r.ability || [
|
||||
} else if (race.lineage === "UA1") {
|
||||
race.ability = race.ability || [
|
||||
{
|
||||
choose: {
|
||||
weighted: {
|
||||
@@ -6470,60 +6478,60 @@ Renderer.race = class {
|
||||
];
|
||||
}
|
||||
|
||||
r.entries = r.entries || [];
|
||||
r.entries.push({
|
||||
race.entries = race.entries || [];
|
||||
race.entries.push({
|
||||
type: "entries",
|
||||
name: "Languages",
|
||||
entries: ["You can speak, read, and write Common and one other language that you and your DM agree is appropriate for your character."],
|
||||
});
|
||||
|
||||
r.languageProficiencies = r.languageProficiencies || [{"common": true, "anyStandard": 1}];
|
||||
race.languageProficiencies = race.languageProficiencies || [{"common": true, "anyStandard": 1}];
|
||||
}
|
||||
|
||||
if (r.subraces && !r.subraces.length) delete r.subraces;
|
||||
if (race.subraces && !race.subraces.length) delete race.subraces;
|
||||
|
||||
if (r.subraces) {
|
||||
r.subraces.forEach(sr => {
|
||||
sr.source = sr.source || r.source;
|
||||
if (race.subraces) {
|
||||
race.subraces.forEach(sr => {
|
||||
sr.source = sr.source || race.source;
|
||||
sr._isSubRace = true;
|
||||
});
|
||||
|
||||
r.subraces.sort((a, b) => SortUtil.ascSortLower(a.name || "_", b.name || "_") || SortUtil.ascSortLower(Parser.sourceJsonToAbv(a.source), Parser.sourceJsonToAbv(b.source)));
|
||||
race.subraces.sort((a, b) => SortUtil.ascSortLower(a.name || "_", b.name || "_") || SortUtil.ascSortLower(Parser.sourceJsonToAbv(a.source), Parser.sourceJsonToAbv(b.source)));
|
||||
}
|
||||
|
||||
if (opts.isAddBaseRaces && r.subraces) {
|
||||
const baseRace = MiscUtil.copyFast(r);
|
||||
if (opts.isAddBaseRaces && race.subraces) {
|
||||
const baseRace = MiscUtil.copyFast(race);
|
||||
|
||||
baseRace._isBaseRace = true;
|
||||
|
||||
const isAnyNoName = r.subraces.some(it => !it.name);
|
||||
const isAnyNoName = race.subraces.some(it => !it.name);
|
||||
if (isAnyNoName) {
|
||||
baseRace._rawName = baseRace.name;
|
||||
baseRace.name = `${baseRace.name} (Base)`;
|
||||
}
|
||||
|
||||
const nameCounts = {};
|
||||
r.subraces.filter(sr => sr.name).forEach(sr => nameCounts[sr.name.toLowerCase()] = (nameCounts[sr.name.toLowerCase()] || 0) + 1);
|
||||
nameCounts._ = r.subraces.filter(sr => !sr.name).length;
|
||||
race.subraces.filter(sr => sr.name).forEach(sr => nameCounts[sr.name.toLowerCase()] = (nameCounts[sr.name.toLowerCase()] || 0) + 1);
|
||||
nameCounts._ = race.subraces.filter(sr => !sr.name).length;
|
||||
|
||||
const lst = {
|
||||
type: "list",
|
||||
items: r.subraces.map(sr => {
|
||||
items: race.subraces.map(sr => {
|
||||
const count = nameCounts[(sr.name || "_").toLowerCase()];
|
||||
const idName = Renderer.race.getSubraceName(r.name, sr.name);
|
||||
const idName = Renderer.race.getSubraceName(race.name, sr.name);
|
||||
return `{@race ${idName}|${sr.source}${count > 1 ? `|${idName} (<span title="${Parser.sourceJsonToFull(sr.source).escapeQuotes()}">${Parser.sourceJsonToAbv(sr.source)}</span>)` : ""}}`;
|
||||
}),
|
||||
};
|
||||
|
||||
Renderer.race._mutBaseRaceEntries(baseRace, lst);
|
||||
baseRace._subraces = r.subraces.map(sr => ({name: Renderer.race.getSubraceName(r.name, sr.name), source: sr.source}));
|
||||
baseRace._subraces = race.subraces.map(sr => ({name: Renderer.race.getSubraceName(race.name, sr.name), source: sr.source}));
|
||||
|
||||
delete baseRace.subraces;
|
||||
|
||||
out.push(baseRace);
|
||||
}
|
||||
|
||||
out.push(...Renderer.race._mergeSubraces(r));
|
||||
out.push(...Renderer.race._mergeSubraces(race));
|
||||
});
|
||||
|
||||
return out;
|
||||
@@ -8954,6 +8962,10 @@ Renderer.item = class {
|
||||
|
||||
Renderer.item._createSpecificVariants_mergeVulnerableResistImmune({specificVariant, inherits});
|
||||
|
||||
// Inherit fluff
|
||||
if (genericVariant.hasFluff) specificVariant.hasFluff = genericVariant.hasFluff;
|
||||
if (genericVariant.hasFluffImages) specificVariant.hasFluffImages = genericVariant.hasFluffImages;
|
||||
|
||||
// track the specific variant on the parent generic, to later render as part of the stats
|
||||
genericVariant.variants = genericVariant.variants || [];
|
||||
if (!genericVariant.variants.some(it => it.base?.name === baseItem.name && it.base?.source === baseItem.source)) genericVariant.variants.push({base: baseItem, specificVariant});
|
||||
@@ -9460,11 +9472,20 @@ Renderer.item = class {
|
||||
return false;
|
||||
}
|
||||
|
||||
static pGetFluff (item) {
|
||||
return Renderer.utils.pGetFluff({
|
||||
static async pGetFluff (item) {
|
||||
const fluffItem = await Renderer.utils.pGetFluff({
|
||||
entity: item,
|
||||
fluffProp: "itemFluff",
|
||||
});
|
||||
if (fluffItem) return fluffItem;
|
||||
|
||||
if (!item._variantName) return null;
|
||||
|
||||
// Inherit generic variant fluff
|
||||
return Renderer.utils.pGetFluff({
|
||||
entity: {name: item._variantName, source: item.source},
|
||||
fluffProp: "itemFluff",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10981,6 +11002,7 @@ Renderer.generic = class {
|
||||
skillToolLanguageProfs,
|
||||
setValid: new Set(this.FEATURE__SKILLS_ALL),
|
||||
setValidAny: this._SKILL_TOOL_LANGUAGE_KEYS__SKILL_ANY,
|
||||
anyAlt: "anySkill",
|
||||
isShort,
|
||||
hoverTag: "skill",
|
||||
});
|
||||
@@ -10992,6 +11014,7 @@ Renderer.generic = class {
|
||||
skillToolLanguageProfs,
|
||||
setValid: new Set(this.FEATURE__TOOLS_ALL),
|
||||
setValidAny: this._SKILL_TOOL_LANGUAGE_KEYS__TOOL_ANY,
|
||||
anyAlt: "anyTool",
|
||||
isShort,
|
||||
});
|
||||
}
|
||||
@@ -11002,11 +11025,12 @@ Renderer.generic = class {
|
||||
skillToolLanguageProfs,
|
||||
setValid: new Set(this.FEATURE__LANGUAGES_ALL),
|
||||
setValidAny: this._SKILL_TOOL_LANGUAGE_KEYS__LANGAUGE_ANY,
|
||||
anyAlt: "anyLanguage",
|
||||
isShort,
|
||||
});
|
||||
}
|
||||
|
||||
static _summariseProfs ({profGroupArr, skillToolLanguageProfs, setValid, setValidAny, isShort, hoverTag}) {
|
||||
static _summariseProfs ({profGroupArr, skillToolLanguageProfs, setValid, setValidAny, anyAlt, isShort, hoverTag}) {
|
||||
if (!profGroupArr?.length && !skillToolLanguageProfs?.length) return {summary: "", collection: []};
|
||||
|
||||
const collectionSet = new Set();
|
||||
@@ -11026,13 +11050,13 @@ Renderer.generic = class {
|
||||
const chooseProfs = vMapped.from
|
||||
.filter(s => !isValidate || setValid.has(s))
|
||||
.map(s => {
|
||||
collectionSet.add(s);
|
||||
collectionSet.add(this._summariseProfs_getCollectionKey(s, anyAlt));
|
||||
return this._summariseProfs_getEntry({str: s, isShort, hoverTag});
|
||||
});
|
||||
return `${isShort ? `${i === 0 ? "C" : "c"}hoose ` : ""}${v.count || 1} ${isShort ? `of` : `from`} ${chooseProfs.joinConjunct(", ", " or ")}`;
|
||||
}
|
||||
|
||||
collectionSet.add(k);
|
||||
collectionSet.add(this._summariseProfs_getCollectionKey(k, anyAlt));
|
||||
return this._summariseProfs_getEntry({str: k, isShort, hoverTag});
|
||||
});
|
||||
|
||||
@@ -11052,6 +11076,10 @@ Renderer.generic = class {
|
||||
return {summary, collection: [...collectionSet].sort(SortUtil.ascSortLower)};
|
||||
}
|
||||
|
||||
static _summariseProfs_getCollectionKey (k, anyAlt) {
|
||||
return k === anyAlt ? "any" : k;
|
||||
}
|
||||
|
||||
static _summariseProfs_sortKeys (a, b, {setValidAny = null} = {}) {
|
||||
if (a === b) return 0;
|
||||
if (a === "choose") return 2;
|
||||
|
||||
@@ -204,9 +204,12 @@ class StatGenUi extends BaseComponent {
|
||||
};
|
||||
}
|
||||
|
||||
_roll_getRolledStats () {
|
||||
async _roll_pGetRolledStats () {
|
||||
const wrpTree = Renderer.dice.lang.getTree3(this._state.rolled_formula);
|
||||
if (!wrpTree) return this._$rollIptFormula.addClass("form-control--error");
|
||||
if (!wrpTree) {
|
||||
this._$rollIptFormula.addClass("form-control--error");
|
||||
return;
|
||||
}
|
||||
|
||||
const rolls = [];
|
||||
for (let i = 0; i < this._state.rolled_rollCount; i++) {
|
||||
@@ -287,9 +290,15 @@ class StatGenUi extends BaseComponent {
|
||||
})
|
||||
.change(() => this._$rollIptFormula.removeClass("form-control--error"));
|
||||
|
||||
const lockRoll = new VeLock();
|
||||
const $btnRoll = $(`<button class="btn btn-primary bold">Roll</button>`)
|
||||
.click(() => {
|
||||
this._state.rolled_rolls = this._roll_getRolledStats();
|
||||
.click(async () => {
|
||||
try {
|
||||
await lockRoll.pLock();
|
||||
this._state.rolled_rolls = await this._roll_pGetRolledStats();
|
||||
} finally {
|
||||
lockRoll.unlock();
|
||||
}
|
||||
});
|
||||
|
||||
const $btnRandom = $(`<button class="btn btn-xs btn-default mt-2">Randomly Assign</button>`)
|
||||
@@ -723,7 +732,7 @@ class StatGenUi extends BaseComponent {
|
||||
};
|
||||
this._proxyAssignSimple("state", nxtState);
|
||||
});
|
||||
$(`<option/>`, {value: -1, text: "\u2014"}).appendTo($selRolled);
|
||||
$(`<option></option>`, {value: -1, text: "\u2014"}).appendTo($selRolled);
|
||||
|
||||
let $optionsRolled = [];
|
||||
const hkRolls = () => {
|
||||
@@ -731,7 +740,7 @@ class StatGenUi extends BaseComponent {
|
||||
|
||||
this._state.rolled_rolls.forEach((it, i) => {
|
||||
const cntPrevRolls = this._state.rolled_rolls.slice(0, i).filter(r => r.total === it.total).length;
|
||||
const $opt = $(`<option/>`, {value: i, text: `${it.total}${cntPrevRolls ? Parser.numberToSubscript(cntPrevRolls) : ""}`}).appendTo($selRolled);
|
||||
const $opt = $(`<option></option>`, {value: i, text: `${it.total}${cntPrevRolls ? Parser.numberToSubscript(cntPrevRolls) : ""}`}).appendTo($selRolled);
|
||||
$optionsRolled.push($opt);
|
||||
});
|
||||
|
||||
@@ -769,9 +778,9 @@ class StatGenUi extends BaseComponent {
|
||||
};
|
||||
this._proxyAssignSimple("state", nxtState);
|
||||
});
|
||||
$(`<option/>`, {value: -1, text: "\u2014"}).appendTo($selArray);
|
||||
$(`<option></option>`, {value: -1, text: "\u2014"}).appendTo($selArray);
|
||||
|
||||
StatGenUi._STANDARD_ARRAY.forEach((it, i) => $(`<option/>`, {value: i, text: it}).appendTo($selArray));
|
||||
StatGenUi._STANDARD_ARRAY.forEach((it, i) => $(`<option></option>`, {value: i, text: it}).appendTo($selArray));
|
||||
|
||||
const hookIxArray = () => {
|
||||
const ix = this._state[propAbilSelectedScoreIx] == null ? -1 : this._state[propAbilSelectedScoreIx];
|
||||
@@ -972,7 +981,7 @@ class StatGenUi extends BaseComponent {
|
||||
this._parent._addHookBase(this._propIxAbilityScoreSet, hkIxEntity);
|
||||
hkIxEntity();
|
||||
|
||||
const {$wrp: $selEntity, fnUpdateHidden: fnUpdateSelEntityHidden} = ComponentUiUtil.$getSelSearchable(
|
||||
const {$wrp: $selEntity, setFnFilter: setFnFilterEntity} = ComponentUiUtil.$getSelSearchable(
|
||||
this._parent,
|
||||
this._propIxEntity,
|
||||
{
|
||||
@@ -989,8 +998,12 @@ class StatGenUi extends BaseComponent {
|
||||
|
||||
const doApplyFilterToSelEntity = () => {
|
||||
const f = this._parent[this._propModalFilter].pageFilter.filterBox.getValues();
|
||||
const isHiddenPerEntity = this._parent[this._propData].map(it => !this._parent[this._propModalFilter].pageFilter.toDisplay(f, it));
|
||||
fnUpdateSelEntityHidden(isHiddenPerEntity, false);
|
||||
setFnFilterEntity(value => {
|
||||
if (value == null) return true;
|
||||
|
||||
const ent = this._parent[this._propData][value];
|
||||
return this._parent[this._propModalFilter].pageFilter.toDisplay(f, ent);
|
||||
});
|
||||
};
|
||||
|
||||
this._parent[this._propModalFilter].pageFilter.filterBox.on(FilterBox.EVNT_VALCHANGE, () => doApplyFilterToSelEntity());
|
||||
@@ -1041,9 +1054,14 @@ class StatGenUi extends BaseComponent {
|
||||
const hkSetValuesSelAbilitySet = () => {
|
||||
const entity = this._parent[this._propEntity];
|
||||
$stgAbilityScoreSet.toggleVe(!!entity && entity.ability?.length > 1);
|
||||
|
||||
// Set to empty array between real sets, as otherwise two matching sets of list indices
|
||||
// will be considered "the same list," even though their display will ultimately be different.
|
||||
// Using a blank list here forces any real list to cause a refresh.
|
||||
setValuesSelAbilitySet([]);
|
||||
|
||||
setValuesSelAbilitySet(
|
||||
[...new Array(entity?.ability?.length || 0)].map((_, ix) => ix),
|
||||
{isForce: true},
|
||||
);
|
||||
};
|
||||
this._parent._addHookBase(this._propIxEntity, hkSetValuesSelAbilitySet);
|
||||
|
||||
@@ -1,6 +1,77 @@
|
||||
"use strict";
|
||||
|
||||
class StyleSwitcher {
|
||||
static _STORAGE_DAY_NIGHT = "StyleSwitcher_style";
|
||||
static _STORAGE_IS_MANUAL_MODE = "StyleSwitcher_style-is-manual-mode";
|
||||
static _STORAGE_WIDE = "StyleSwitcher_style-wide";
|
||||
|
||||
static _STYLE_DAY = "day";
|
||||
static _STYLE_NIGHT = "night";
|
||||
static _STYLE_NIGHT_ALT = "nightAlt";
|
||||
static _STYLE_NIGHT_CLEAN = "nightClean";
|
||||
|
||||
static _NIGHT_CLASS = "ve-night-mode";
|
||||
static _NIGHT_CLASS_STANDARD = "ve-night-mode--standard";
|
||||
static _NIGHT_CLASS_ALT = "ve-night-mode--classic";
|
||||
static _NIGHT_CLASS_CLEAN = "ve-night-mode--clean";
|
||||
|
||||
static _WIDE_ID = "style-switch__wide";
|
||||
|
||||
static _STYLES = [
|
||||
this._STYLE_DAY,
|
||||
this._STYLE_NIGHT,
|
||||
this._STYLE_NIGHT_ALT,
|
||||
this._STYLE_NIGHT_CLEAN,
|
||||
];
|
||||
|
||||
static _STYLE_TO_DISPLAY_NAME = {
|
||||
[this._STYLE_DAY]: "Day Mode",
|
||||
[this._STYLE_NIGHT]: "Night Mode",
|
||||
[this._STYLE_NIGHT_ALT]: "Night Mode (Classic)",
|
||||
[this._STYLE_NIGHT_CLEAN]: "Night Mode (Clean)",
|
||||
};
|
||||
|
||||
static _STYLE_CLASSES = [
|
||||
this._NIGHT_CLASS,
|
||||
this._NIGHT_CLASS_STANDARD,
|
||||
this._NIGHT_CLASS_ALT,
|
||||
this._NIGHT_CLASS_CLEAN,
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static getSelStyle () {
|
||||
const selStyle = e_({
|
||||
tag: "select",
|
||||
clazz: "form-control input-xs",
|
||||
children: Object.entries(this._STYLE_TO_DISPLAY_NAME)
|
||||
.map(([id, name]) => ee`<option value="${id}">${name}</option>`),
|
||||
change: () => {
|
||||
styleSwitcher._setActiveDayNight(selStyle.val());
|
||||
StyleSwitcher.storage.setItem(StyleSwitcher._STORAGE_IS_MANUAL_MODE, true);
|
||||
},
|
||||
})
|
||||
.val(styleSwitcher.currentStylesheet);
|
||||
|
||||
return selStyle;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static getCbWide () {
|
||||
const cbWide = e_({
|
||||
tag: "input",
|
||||
type: "checkbox",
|
||||
change: () => {
|
||||
styleSwitcher._setActiveWide(cbWide.checked);
|
||||
},
|
||||
});
|
||||
|
||||
return cbWide;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
constructor () {
|
||||
this.currentStylesheet = StyleSwitcher._STYLE_DAY;
|
||||
|
||||
@@ -30,15 +101,16 @@ class StyleSwitcher {
|
||||
_setActiveDayNight (style) {
|
||||
this.currentStylesheet = style;
|
||||
|
||||
this.constructor._STYLE_CLASSES
|
||||
.forEach(clazzName => document.documentElement.classList.remove(clazzName));
|
||||
|
||||
switch (style) {
|
||||
case StyleSwitcher._STYLE_DAY: {
|
||||
document.documentElement.classList.remove(StyleSwitcher._NIGHT_CLASS);
|
||||
document.documentElement.classList.remove(StyleSwitcher._NIGHT_CLASS_ALT);
|
||||
break;
|
||||
}
|
||||
case StyleSwitcher._STYLE_NIGHT: {
|
||||
document.documentElement.classList.add(StyleSwitcher._NIGHT_CLASS);
|
||||
document.documentElement.classList.remove(StyleSwitcher._NIGHT_CLASS_ALT);
|
||||
document.documentElement.classList.add(StyleSwitcher._NIGHT_CLASS_STANDARD);
|
||||
break;
|
||||
}
|
||||
case StyleSwitcher._STYLE_NIGHT_ALT: {
|
||||
@@ -46,10 +118,13 @@ class StyleSwitcher {
|
||||
document.documentElement.classList.add(StyleSwitcher._NIGHT_CLASS_ALT);
|
||||
break;
|
||||
}
|
||||
case StyleSwitcher._STYLE_NIGHT_CLEAN: {
|
||||
document.documentElement.classList.add(StyleSwitcher._NIGHT_CLASS);
|
||||
document.documentElement.classList.add(StyleSwitcher._NIGHT_CLASS_CLEAN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
StyleSwitcher._setButtonText("nightModeToggle", this.getDayNightButtonText(style));
|
||||
|
||||
StyleSwitcher.storage.setItem(StyleSwitcher._STORAGE_DAY_NIGHT, this.currentStylesheet);
|
||||
|
||||
this._fnsOnChange.forEach(fn => fn());
|
||||
@@ -58,16 +133,9 @@ class StyleSwitcher {
|
||||
getDayNightClassNames () {
|
||||
switch (this.currentStylesheet) {
|
||||
case StyleSwitcher._STYLE_DAY: return "";
|
||||
case StyleSwitcher._STYLE_NIGHT: return StyleSwitcher._NIGHT_CLASS;
|
||||
case StyleSwitcher._STYLE_NIGHT: return [StyleSwitcher._NIGHT_CLASS, StyleSwitcher._NIGHT_CLASS_STANDARD].join(" ");
|
||||
case StyleSwitcher._STYLE_NIGHT_ALT: return [StyleSwitcher._NIGHT_CLASS, StyleSwitcher._NIGHT_CLASS_ALT].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
getDayNightButtonText () {
|
||||
switch (this.currentStylesheet) {
|
||||
case StyleSwitcher._STYLE_NIGHT_ALT: return "Day Mode";
|
||||
case StyleSwitcher._STYLE_DAY: return "Night Mode";
|
||||
case StyleSwitcher._STYLE_NIGHT: return "Night Mode (Alt)";
|
||||
case StyleSwitcher._STYLE_NIGHT_CLEAN: return [StyleSwitcher._NIGHT_CLASS, StyleSwitcher._NIGHT_CLASS_CLEAN].join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +145,14 @@ class StyleSwitcher {
|
||||
}
|
||||
|
||||
cycleDayNightMode (direction) {
|
||||
const newStyle = direction === -1
|
||||
? this.currentStylesheet === StyleSwitcher._STYLE_DAY ? StyleSwitcher._STYLE_NIGHT_ALT : this.currentStylesheet === StyleSwitcher._STYLE_NIGHT ? StyleSwitcher._STYLE_DAY : StyleSwitcher._STYLE_NIGHT
|
||||
: this.currentStylesheet === StyleSwitcher._STYLE_DAY ? StyleSwitcher._STYLE_NIGHT : this.currentStylesheet === StyleSwitcher._STYLE_NIGHT ? StyleSwitcher._STYLE_NIGHT_ALT : StyleSwitcher._STYLE_DAY;
|
||||
const ixCur = this.constructor._STYLES.indexOf(this.currentStylesheet);
|
||||
const ixNxt = ixCur === 0
|
||||
? this.constructor._STYLES.length - 1
|
||||
: ixCur === this.constructor._STYLES.length - 1
|
||||
? 0
|
||||
: ixCur + direction;
|
||||
const newStyle = this.constructor._STYLES[ixNxt];
|
||||
|
||||
this._setActiveDayNight(newStyle);
|
||||
StyleSwitcher.storage.setItem(StyleSwitcher._STORAGE_IS_MANUAL_MODE, true);
|
||||
}
|
||||
@@ -143,15 +216,6 @@ class StyleSwitcher {
|
||||
getActiveWide () { return document.getElementById(StyleSwitcher._WIDE_ID) != null; }
|
||||
// endregion
|
||||
}
|
||||
StyleSwitcher._STORAGE_DAY_NIGHT = "StyleSwitcher_style";
|
||||
StyleSwitcher._STORAGE_IS_MANUAL_MODE = "StyleSwitcher_style-is-manual-mode";
|
||||
StyleSwitcher._STORAGE_WIDE = "StyleSwitcher_style-wide";
|
||||
StyleSwitcher._STYLE_DAY = "day";
|
||||
StyleSwitcher._STYLE_NIGHT = "night";
|
||||
StyleSwitcher._STYLE_NIGHT_ALT = "nightAlt";
|
||||
StyleSwitcher._NIGHT_CLASS = "ve-night-mode";
|
||||
StyleSwitcher._NIGHT_CLASS_ALT = "ve-night-mode--alt";
|
||||
StyleSwitcher._WIDE_ID = "style-switch__wide";
|
||||
|
||||
try {
|
||||
StyleSwitcher.storage = window.localStorage;
|
||||
|
||||
5
js/utils-config.js
Normal file
5
js/utils-config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import {VetoolsConfig} from "./utils-config/utils-config-config.js";
|
||||
import {ConfigUi} from "./utils-config/utils-config-ui.js";
|
||||
|
||||
globalThis.VetoolsConfig = VetoolsConfig;
|
||||
globalThis.ConfigUi = ConfigUi;
|
||||
10
js/utils-config/util-config-helpers.js
Normal file
10
js/utils-config/util-config-helpers.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export class UtilConfigHelpers {
|
||||
static packSettingId (groupId, configId) {
|
||||
return `${groupId}.${configId}`;
|
||||
}
|
||||
|
||||
static unpackSettingId (settingId) {
|
||||
const [groupId, configId] = settingId.split(".");
|
||||
return {groupId, configId};
|
||||
}
|
||||
}
|
||||
38
js/utils-config/util-config-settings-group.js
Normal file
38
js/utils-config/util-config-settings-group.js
Normal file
@@ -0,0 +1,38 @@
|
||||
export class ConfigSettingsGroup {
|
||||
constructor (
|
||||
{
|
||||
groupId,
|
||||
name,
|
||||
configSettings,
|
||||
},
|
||||
) {
|
||||
this._groupId = groupId;
|
||||
this._name = name;
|
||||
this._configSettings = configSettings;
|
||||
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.setGroupId(this._groupId));
|
||||
}
|
||||
|
||||
get groupId () { return this._groupId; }
|
||||
|
||||
render (rdState, {isLast = false} = {}) {
|
||||
const wrpRows = ee`<div></div>`;
|
||||
|
||||
ee`<div class="w-100">
|
||||
<h4>${this._name}</h4>
|
||||
${wrpRows}
|
||||
${isLast ? null : `<hr class="hr-3 mb-1">`}
|
||||
</div>`
|
||||
.appendTo(rdState.wrp);
|
||||
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.render(rdState, wrpRows));
|
||||
}
|
||||
|
||||
mutDefaults (config) {
|
||||
const group = config[this._groupId] ||= {};
|
||||
this._configSettings
|
||||
.forEach(configSetting => configSetting.mutDefaults(group));
|
||||
}
|
||||
}
|
||||
66
js/utils-config/utils-config-config.js
Normal file
66
js/utils-config/utils-config-config.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import {SETTINGS_GROUPS} from "./utils-config-registry.js";
|
||||
import {UtilConfigHelpers} from "./util-config-helpers.js";
|
||||
|
||||
export class VetoolsConfig {
|
||||
static _STORAGE_KEY = "config";
|
||||
|
||||
static _CONFIG = null;
|
||||
|
||||
static _init () {
|
||||
if (this._CONFIG) return;
|
||||
|
||||
this._CONFIG = StorageUtil.syncGet(this._STORAGE_KEY) || {};
|
||||
|
||||
SETTINGS_GROUPS
|
||||
.forEach(settingsGroup => settingsGroup.mutDefaults(this._CONFIG));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static get (groupId, configId) {
|
||||
this._init();
|
||||
return MiscUtil.get(this._CONFIG, groupId, configId);
|
||||
}
|
||||
|
||||
static set (groupId, configId, val) {
|
||||
this._init();
|
||||
MiscUtil.set(this._CONFIG, groupId, configId, val);
|
||||
this._save();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _save () {
|
||||
StorageUtil.syncSet(this._STORAGE_KEY, this._CONFIG);
|
||||
}
|
||||
|
||||
static _saveThrottled = MiscUtil.throttle(this._save.bind(this), 50);
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static getConfigComp () {
|
||||
this._init();
|
||||
|
||||
const state = {};
|
||||
Object.entries(this._CONFIG)
|
||||
.forEach(([groupId, groupTo]) => {
|
||||
Object.entries(groupTo)
|
||||
.forEach(([configId, val]) => {
|
||||
state[UtilConfigHelpers.packSettingId(groupId, configId)] = MiscUtil.copyFast(val);
|
||||
});
|
||||
});
|
||||
|
||||
const comp = BaseComponent.fromObject(state, "*");
|
||||
comp._addHookAllBase(() => {
|
||||
Object.entries(comp._state)
|
||||
.forEach(([settingId, v]) => {
|
||||
const {groupId, configId} = UtilConfigHelpers.unpackSettingId(settingId);
|
||||
MiscUtil.set(this._CONFIG, groupId, configId, v);
|
||||
});
|
||||
|
||||
this._saveThrottled();
|
||||
});
|
||||
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
74
js/utils-config/utils-config-registry.js
Normal file
74
js/utils-config/utils-config-registry.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import {ConfigSettingsGroup} from "./util-config-settings-group.js";
|
||||
import {ConfigSettingBoolean, ConfigSettingEnum, ConfigSettingExternal} from "./utils-config-setting-base.js";
|
||||
|
||||
const settingsGroupStyleSwitcher = new ConfigSettingsGroup({
|
||||
groupId: "styleSwitcher",
|
||||
name: "Appearance",
|
||||
configSettings: [
|
||||
new (
|
||||
class extends ConfigSettingExternal {
|
||||
_configId = "theme";
|
||||
_name = "Theme";
|
||||
_help = "The color theme to be applied.";
|
||||
_isRowLabel = true;
|
||||
|
||||
_getEleExternal () { return StyleSwitcher.getSelStyle(); }
|
||||
}
|
||||
)(),
|
||||
new (
|
||||
class extends ConfigSettingExternal {
|
||||
_configId = "isWideMode";
|
||||
_name = "Wide Mode (Experimental)";
|
||||
_help = "This feature is unsupported. Expect bugs.";
|
||||
_isRowLabel = true;
|
||||
|
||||
_getEleExternal () { return StyleSwitcher.getCbWide(); }
|
||||
}
|
||||
)(),
|
||||
],
|
||||
});
|
||||
|
||||
const _MARKDOWN_TAG_RENDER_MODES = {
|
||||
"convertMarkdown": "Convert to Markdown",
|
||||
"ignore": "Leave As-Is",
|
||||
"convertText": "Convert to Text",
|
||||
};
|
||||
|
||||
const settingsGroupMarkdown = new ConfigSettingsGroup({
|
||||
groupId: "markdown",
|
||||
name: "Markdown",
|
||||
configSettings: [
|
||||
new ConfigSettingEnum({
|
||||
configId: "tagRenderMode",
|
||||
name: `Tag Handling (<code>@tag</code>)`,
|
||||
help: `THe output to produce when rendering a 5etools "@tag".`,
|
||||
isRowLabel: true,
|
||||
default: "convertMarkdown",
|
||||
values: [
|
||||
"convertMarkdown",
|
||||
"ignore",
|
||||
"convertText",
|
||||
],
|
||||
fnDisplay: it => _MARKDOWN_TAG_RENDER_MODES[it] || it,
|
||||
}),
|
||||
new ConfigSettingBoolean({
|
||||
configId: "isAddColumnBreaks",
|
||||
name: `Add GM Binder Column Breaks (<code>\\\\columnbreak</code>)`,
|
||||
help: `If "\\\\columnbreak"s should be added to exported Markdown, at an approximate column breakpoint.`,
|
||||
isRowLabel: true,
|
||||
default: false,
|
||||
}),
|
||||
new ConfigSettingBoolean({
|
||||
configId: "isAddPageBreaks",
|
||||
name: `Add GM Binder Page Breaks (<code>\\\\pagebreak</code>)`,
|
||||
help: `If "\\\\pagebreak"s should be added to exported Markdown, at an approximate page breakpoint.`,
|
||||
isRowLabel: true,
|
||||
default: false,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const SETTINGS_GROUPS = [
|
||||
settingsGroupStyleSwitcher,
|
||||
settingsGroupMarkdown,
|
||||
];
|
||||
118
js/utils-config/utils-config-setting-base.js
Normal file
118
js/utils-config/utils-config-setting-base.js
Normal file
@@ -0,0 +1,118 @@
|
||||
import {UtilConfigHelpers} from "./util-config-helpers.js";
|
||||
|
||||
// TODO rename this file
|
||||
|
||||
/** @abstract */
|
||||
class _ConfigSettingBase {
|
||||
_groupId;
|
||||
_configId;
|
||||
_name;
|
||||
_help;
|
||||
|
||||
_isRowLabel = false;
|
||||
|
||||
constructor (
|
||||
{
|
||||
configId,
|
||||
name,
|
||||
help,
|
||||
|
||||
isRowLabel,
|
||||
} = {},
|
||||
) {
|
||||
this._configId = configId;
|
||||
this._name = name;
|
||||
this._help = help;
|
||||
this._isRowLabel = isRowLabel;
|
||||
}
|
||||
|
||||
setGroupId (groupId) { this._groupId = groupId; }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
render (rdState, wrpRows) {
|
||||
const tag = this._isRowLabel ? "label" : "div";
|
||||
|
||||
ee`<${tag} class="py-1 w-100 split-v-center" title="${this._help.qq()}">
|
||||
${this._renderLabel(rdState)}
|
||||
${this._renderUi(rdState)}
|
||||
</${tag}>`
|
||||
.appendTo(wrpRows);
|
||||
}
|
||||
|
||||
_renderLabel (rdState) {
|
||||
return `<div class="w-66 no-shrink mr-2">${this._name}</div>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
_renderUi (rdState) { throw new Error("Unimplemented!"); }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @abstract */
|
||||
mutDefaults (group) {
|
||||
throw new Error("Unimplemented!");
|
||||
}
|
||||
}
|
||||
|
||||
/** @abstract */
|
||||
export class ConfigSettingExternal extends _ConfigSettingBase {
|
||||
_renderUi (rdState) { return this._getEleExternal(); }
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
_getEleExternal () { throw new Error("Unimplemented!"); }
|
||||
|
||||
mutDefaults (group) { /* No-op */ }
|
||||
}
|
||||
|
||||
/** @abstract */
|
||||
class _ConfigSettingStandardBase extends _ConfigSettingBase {
|
||||
_default;
|
||||
|
||||
constructor (opts) {
|
||||
super(opts);
|
||||
this._default = opts.default;
|
||||
}
|
||||
|
||||
mutDefaults (group) {
|
||||
if (group[this._configId] !== undefined) return;
|
||||
group[this._configId] = this._default;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigSettingBoolean extends _ConfigSettingStandardBase {
|
||||
_renderUi (rdState) {
|
||||
const prop = UtilConfigHelpers.packSettingId(this._groupId, this._configId);
|
||||
return ComponentUiUtil.getCbBool(rdState.comp, prop);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigSettingEnum extends _ConfigSettingStandardBase {
|
||||
_values;
|
||||
_fnDisplay;
|
||||
|
||||
constructor ({values, fnDisplay, ...rest}) {
|
||||
super(rest);
|
||||
this._values = values;
|
||||
this._fnDisplay = fnDisplay;
|
||||
}
|
||||
|
||||
_renderUi (rdState) {
|
||||
const prop = UtilConfigHelpers.packSettingId(this._groupId, this._configId);
|
||||
|
||||
return ComponentUiUtil.getSelEnum(
|
||||
rdState.comp,
|
||||
prop,
|
||||
{
|
||||
values: this._values,
|
||||
fnDisplay: this._fnDisplay,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
79
js/utils-config/utils-config-ui.js
Normal file
79
js/utils-config/utils-config-ui.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import {VetoolsConfig} from "./utils-config-config.js";
|
||||
import {SETTINGS_GROUPS} from "./utils-config-registry.js";
|
||||
|
||||
class _ConfigRenderState {
|
||||
wrp;
|
||||
comp;
|
||||
|
||||
constructor (
|
||||
{
|
||||
wrp,
|
||||
comp,
|
||||
},
|
||||
) {
|
||||
this.wrp = wrp;
|
||||
this.comp = comp;
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigUi {
|
||||
constructor (
|
||||
{
|
||||
settingsGroups,
|
||||
},
|
||||
) {
|
||||
this._settingsGroups = settingsGroups;
|
||||
}
|
||||
|
||||
render (wrp) {
|
||||
const rdState = new _ConfigRenderState({
|
||||
wrp,
|
||||
comp: VetoolsConfig.getConfigComp(),
|
||||
});
|
||||
|
||||
this._settingsGroups
|
||||
.forEach((configSection, i, arr) => {
|
||||
configSection.render(rdState, {isLast: i === arr.length - 1});
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @param {?string[]} settingsGroupIds Subset of group IDs to display
|
||||
*/
|
||||
static show (
|
||||
{
|
||||
settingsGroupIds = null,
|
||||
} = {},
|
||||
) {
|
||||
const settingsGroups = settingsGroupIds
|
||||
? SETTINGS_GROUPS
|
||||
.filter(group => settingsGroupIds.includes(group.groupId))
|
||||
: SETTINGS_GROUPS;
|
||||
|
||||
const ui = new this({
|
||||
settingsGroups,
|
||||
});
|
||||
|
||||
const {$modalInner, $modalFooter, doClose} = UiUtil.getShowModal({
|
||||
isUncappedWidth: true,
|
||||
isUncappedHeight: true,
|
||||
title: "Preferences",
|
||||
headerType: 3,
|
||||
isHeaderBorder: true,
|
||||
overlayColor: "transparent",
|
||||
hasFooter: true,
|
||||
});
|
||||
|
||||
ui.render($modalInner[0]);
|
||||
|
||||
const btnClose = ee`<button class="btn btn-default btn-sm ml-auto">Close</button>`
|
||||
.onn("click", () => doClose());
|
||||
|
||||
ee`<div class="py-1 w-100 ve-flex-v-center">
|
||||
${btnClose}
|
||||
</div>`
|
||||
.appendTo($modalFooter[0]);
|
||||
}
|
||||
}
|
||||
@@ -988,13 +988,6 @@ class _DataTypeLoaderLanguage extends _DataTypeLoaderPredefined {
|
||||
_loader = "language";
|
||||
}
|
||||
|
||||
class _DataTypeLoaderRecipe extends _DataTypeLoaderPredefined {
|
||||
static PROPS = ["recipe"];
|
||||
static PAGE = UrlUtil.PG_RECIPES;
|
||||
|
||||
_loader = "recipe";
|
||||
}
|
||||
|
||||
class _DataTypeLoaderMultiSource extends _DataTypeLoader {
|
||||
_prop;
|
||||
|
||||
@@ -1452,6 +1445,59 @@ class _DataTypeLoaderCustomDeck extends _DataTypeLoaderCustomRawable {
|
||||
}
|
||||
}
|
||||
|
||||
class _DataTypeLoaderRecipe extends _DataTypeLoaderCustomRawable {
|
||||
static PROPS = ["raw_recipe", "recipe"];
|
||||
static PAGE = UrlUtil.PG_RECIPES;
|
||||
|
||||
static _PROPS_RAWABLE = ["recipe"];
|
||||
|
||||
async _pGetRawSiteData () { return DataUtil.recipe.loadRawJSON(); }
|
||||
|
||||
async _pGetPostCacheData_obj ({obj, lockToken2}) {
|
||||
if (!obj) return null;
|
||||
|
||||
const out = {};
|
||||
|
||||
if (obj.raw_recipe?.length) out.recipe = await obj.raw_recipe.pSerialAwaitMap(ent => this.constructor._pGetDereferencedRecipeData(ent, {lockToken2}));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static async _pGetDereferencedRecipeData (recipe, {lockToken2}) {
|
||||
recipe = MiscUtil.copyFast(recipe);
|
||||
|
||||
Renderer.recipe.populateFullIngredients(recipe);
|
||||
|
||||
const fluff = await this._pGetDereferencedFluffData(recipe, {lockToken2});
|
||||
if (fluff) recipe.fluff = fluff;
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
static async _pGetDereferencedFluffData (recipe, {lockToken2}) {
|
||||
const fluff = await Renderer.utils.pGetFluff({
|
||||
entity: recipe,
|
||||
fluffProp: "recipeFluff",
|
||||
lockToken2,
|
||||
});
|
||||
if (!fluff) return null;
|
||||
|
||||
const cpyFluff = MiscUtil.copyFast(fluff);
|
||||
delete cpyFluff.name;
|
||||
delete cpyFluff.source;
|
||||
|
||||
return cpyFluff;
|
||||
}
|
||||
|
||||
async pGetPostCacheData ({siteData = null, prereleaseData = null, brewData = null, lockToken2}) {
|
||||
return {
|
||||
siteDataPostCache: await this._pGetPostCacheData_obj_withCache({obj: siteData, lockToken2, propCache: "site"}),
|
||||
prereleaseDataPostCache: await this._pGetPostCacheData_obj({obj: prereleaseData, lockToken2}),
|
||||
brewDataPostCache: await this._pGetPostCacheData_obj({obj: brewData, lockToken2}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class _DataTypeLoaderCustomQuickref extends _DataTypeLoader {
|
||||
static PROPS = ["reference", "referenceData"];
|
||||
static PAGE = UrlUtil.PG_QUICKREF;
|
||||
|
||||
@@ -1,6 +1,151 @@
|
||||
"use strict";
|
||||
|
||||
function getFnListSort (prop) {
|
||||
switch (prop) {
|
||||
case "spell":
|
||||
case "roll20Spell":
|
||||
case "foundrySpell":
|
||||
case "spellList":
|
||||
case "monster":
|
||||
case "foundryMonster":
|
||||
case "monsterFluff":
|
||||
case "monsterTemplate":
|
||||
case "makebrewCreatureTrait":
|
||||
case "makebrewCreatureAction":
|
||||
case "action":
|
||||
case "foundryAction":
|
||||
case "background":
|
||||
case "legendaryGroup":
|
||||
case "language":
|
||||
case "languageScript":
|
||||
case "name":
|
||||
case "condition":
|
||||
case "disease":
|
||||
case "status":
|
||||
case "cult":
|
||||
case "boon":
|
||||
case "feat":
|
||||
case "foundryFeat":
|
||||
case "vehicle":
|
||||
case "vehicleUpgrade":
|
||||
case "foundryVehicleUpgrade":
|
||||
case "backgroundFluff":
|
||||
case "featFluff":
|
||||
case "optionalfeatureFluff":
|
||||
case "conditionFluff":
|
||||
case "spellFluff":
|
||||
case "itemFluff":
|
||||
case "languageFluff":
|
||||
case "vehicleFluff":
|
||||
case "objectFluff":
|
||||
case "raceFluff":
|
||||
case "item":
|
||||
case "foundryItem":
|
||||
case "baseitem":
|
||||
case "magicvariant":
|
||||
case "foundryMagicvariant":
|
||||
case "itemGroup":
|
||||
case "itemMastery":
|
||||
case "object":
|
||||
case "optionalfeature":
|
||||
case "foundryOptionalfeature":
|
||||
case "psionic":
|
||||
case "reward":
|
||||
case "foundryReward":
|
||||
case "rewardFluff":
|
||||
case "variantrule":
|
||||
case "race":
|
||||
case "foundryRace":
|
||||
case "foundryRaceFeature":
|
||||
case "table":
|
||||
case "trap":
|
||||
case "trapFluff":
|
||||
case "hazard":
|
||||
case "hazardFluff":
|
||||
case "charoption":
|
||||
case "charoptionFluff":
|
||||
case "recipe":
|
||||
case "recipeFluff":
|
||||
case "sense":
|
||||
case "skill":
|
||||
case "deck":
|
||||
case "citation":
|
||||
case "foundryMap":
|
||||
return SortUtil.ascSortGenericEntity.bind(SortUtil);
|
||||
case "deity":
|
||||
return SortUtil.ascSortDeity.bind(SortUtil);
|
||||
case "card":
|
||||
return SortUtil.ascSortCard.bind(SortUtil);
|
||||
case "class":
|
||||
case "classFluff":
|
||||
case "foundryClass":
|
||||
return (a, b) => SortUtil.ascSortDateString(Parser.sourceJsonToDate(b.source), Parser.sourceJsonToDate(a.source)) || SortUtil.ascSortLower(a.name, b.name) || SortUtil.ascSortLower(a.source, b.source);
|
||||
case "subclass":
|
||||
case "subclassFluff":
|
||||
case "foundrySubclass":
|
||||
return (a, b) => SortUtil.ascSortDateString(Parser.sourceJsonToDate(b.source), Parser.sourceJsonToDate(a.source)) || SortUtil.ascSortLower(a.name, b.name);
|
||||
case "classFeature":
|
||||
case "foundryClassFeature":
|
||||
return (a, b) => SortUtil.ascSortLower(a.classSource, b.classSource)
|
||||
|| SortUtil.ascSortLower(a.className, b.className)
|
||||
|| SortUtil.ascSort(a.level, b.level)
|
||||
|| SortUtil.ascSortGenericEntity(a, b);
|
||||
case "subclassFeature":
|
||||
case "foundrySubclassFeature":
|
||||
return (a, b) => SortUtil.ascSortLower(a.classSource, b.classSource)
|
||||
|| SortUtil.ascSortLower(a.className, b.className)
|
||||
|| SortUtil.ascSortLower(a.subclassSource, b.subclassSource)
|
||||
|| SortUtil.ascSortLower(a.subclassShortName, b.subclassShortName)
|
||||
|| SortUtil.ascSort(a.level, b.level)
|
||||
|| SortUtil.ascSort(a.header || 0, b.header || 0)
|
||||
|| SortUtil.ascSortGenericEntity(a, b);
|
||||
case "subrace": return (a, b) => SortUtil.ascSortLower(a.raceName, b.raceName)
|
||||
|| SortUtil.ascSortLower(a.raceSource, b.raceSource)
|
||||
|| SortUtil.ascSortLower(a.name || "", b.name || "")
|
||||
|| SortUtil.ascSortLower(a.source, b.source);
|
||||
case "backgroundFeature": return (a, b) => SortUtil.ascSortLower(a.backgroundName, b.backgroundName)
|
||||
|| SortUtil.ascSortLower(a.backgroundSource, b.backgroundSource)
|
||||
|| SortUtil.ascSortGenericEntity(a, b);
|
||||
case "encounter":
|
||||
return SortUtil.ascSortEncounter.bind(SortUtil);
|
||||
case "adventure": return SortUtil.ascSortAdventure.bind(SortUtil);
|
||||
case "book": return SortUtil.ascSortBook.bind(SortUtil);
|
||||
case "adventureData":
|
||||
case "bookData":
|
||||
return SortUtil.ascSortBookData.bind(SortUtil);
|
||||
case "monsterfeatures":
|
||||
return (a, b) => SortUtil.ascSortLower(a.name, b.name);
|
||||
default: throw new Error(`Unhandled prop "${prop}"`);
|
||||
}
|
||||
}
|
||||
|
||||
class PropOrder {
|
||||
static _getKeyProp (keyInfo) {
|
||||
return typeof keyInfo === "string" ? keyInfo : keyInfo.key;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @param obj
|
||||
* @param [opts] Options object.
|
||||
* @param [opts.fnUnhandledKey] Function to call on each unhandled key.
|
||||
* @param [opts.isFoundryPrefixProps] If root keys should be treated as having a "foundry" prefix.
|
||||
*/
|
||||
static getOrderedRoot (obj, opts) {
|
||||
opts ||= {};
|
||||
|
||||
return this._getOrdered(obj, PropOrder._ROOT, opts, "root");
|
||||
}
|
||||
|
||||
static hasOrderRoot (obj) {
|
||||
return PropOrder._ROOT
|
||||
.filter(keyInfo => !(keyInfo instanceof PropOrder._IgnoredKey))
|
||||
.some(keyInfo => obj[this._getKeyProp(keyInfo)] != null);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @param obj
|
||||
* @param dataProp
|
||||
@@ -8,7 +153,7 @@ class PropOrder {
|
||||
* @param [opts.fnUnhandledKey] Function to call on each unhandled key.
|
||||
*/
|
||||
static getOrdered (obj, dataProp, opts) {
|
||||
opts = opts || {};
|
||||
opts ||= {};
|
||||
|
||||
const order = PropOrder._PROP_TO_LIST[dataProp];
|
||||
if (!order) throw new Error(`Unhandled prop "${dataProp}"`);
|
||||
@@ -16,44 +161,79 @@ class PropOrder {
|
||||
return this._getOrdered(obj, order, opts, dataProp);
|
||||
}
|
||||
|
||||
static _getOrdered (obj, order, opts, path) {
|
||||
static _getModifiedProp ({keyInfo, isFoundryPrefixProps}) {
|
||||
const prop = this._getKeyProp(keyInfo);
|
||||
|
||||
if (!isFoundryPrefixProps || prop.startsWith("_")) return prop;
|
||||
|
||||
return prop.replace(/^foundry/, "").lowercaseFirst();
|
||||
}
|
||||
|
||||
static _getOrdered (obj, order, opts, logPath) {
|
||||
const out = {};
|
||||
const keySet = new Set(Object.keys(obj));
|
||||
const seenKeys = new Set();
|
||||
order.forEach(k => {
|
||||
if (typeof k === "string") {
|
||||
seenKeys.add(k);
|
||||
if (keySet.has(k)) out[k] = obj[k];
|
||||
} else {
|
||||
const key = k.key;
|
||||
|
||||
seenKeys.add(key);
|
||||
order
|
||||
.forEach(keyInfo => {
|
||||
const prop = this._getKeyProp(keyInfo);
|
||||
const propMod = this._getModifiedProp({keyInfo, isFoundryPrefixProps: opts.isFoundryPrefixProps});
|
||||
|
||||
if (keySet.has(key)) {
|
||||
if (!obj[key]) return out[key] = obj[key]; // Handle nulls
|
||||
if (opts.isFoundryPrefixProps && !prop.startsWith("_") && !prop.startsWith("foundry")) return;
|
||||
|
||||
if (k instanceof PropOrder._ObjectKey) {
|
||||
const nxtPath = `${path}.${key}`;
|
||||
if (k.fnGetOrder) out[key] = this._getOrdered(obj[key], k.fnGetOrder(obj[key]), opts, nxtPath);
|
||||
else if (k.order) out[key] = this._getOrdered(obj[key], k.order, opts, nxtPath);
|
||||
else out[key] = obj[key];
|
||||
} else if (k instanceof PropOrder._ArrayKey) {
|
||||
const nxtPath = `${path}[n].${key}`;
|
||||
if (k.fnGetOrder) out[key] = obj[key].map(it => this._getOrdered(it, k.fnGetOrder(obj[key]), opts, nxtPath));
|
||||
else if (k.order) out[key] = obj[key].map(it => this._getOrdered(it, k.order, opts, nxtPath));
|
||||
else out[key] = obj[key];
|
||||
if (!keySet.has(propMod)) return;
|
||||
seenKeys.add(propMod);
|
||||
|
||||
if (k.fnSort && out[key] instanceof Array) out[key].sort(k.fnSort);
|
||||
} else throw new Error(`Unimplemented!`);
|
||||
if (typeof keyInfo === "string") {
|
||||
out[propMod] = obj[propMod];
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!obj[propMod]) return out[propMod] = obj[propMod]; // Handle nulls
|
||||
|
||||
const optsNxt = {
|
||||
...opts,
|
||||
// Only used at the root
|
||||
isFoundryPrefixProps: false,
|
||||
};
|
||||
|
||||
if (keyInfo instanceof PropOrder._ObjectKey) {
|
||||
const logPathNxt = `${logPath}.${prop}${propMod !== prop ? ` (${propMod})` : ""}`;
|
||||
if (keyInfo.fnGetOrder) out[propMod] = this._getOrdered(obj[propMod], keyInfo.fnGetOrder(obj[propMod]), optsNxt, logPathNxt);
|
||||
else if (keyInfo.order) out[propMod] = this._getOrdered(obj[propMod], keyInfo.order, optsNxt, logPathNxt);
|
||||
else out[propMod] = obj[propMod];
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyInfo instanceof PropOrder._ArrayKey) {
|
||||
const logPathNxt = `${logPath}[n].${prop}${propMod !== prop ? ` (${propMod})` : ""}`;
|
||||
if (keyInfo.fnGetOrder) out[propMod] = obj[propMod].map(it => this._getOrdered(it, keyInfo.fnGetOrder(obj[propMod]), optsNxt, logPathNxt));
|
||||
else if (keyInfo.order) out[propMod] = obj[propMod].map(it => this._getOrdered(it, keyInfo.order, optsNxt, logPathNxt));
|
||||
else out[propMod] = obj[propMod];
|
||||
|
||||
if (keyInfo.fnSort && out[propMod] instanceof Array) out[propMod].sort(keyInfo.fnSort);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyInfo instanceof PropOrder._IgnoredKey) {
|
||||
out[propMod] = obj[propMod];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Unimplemented!`);
|
||||
});
|
||||
|
||||
// ensure any non-orderable keys are maintained
|
||||
const otherKeys = CollectionUtil.setDiff(keySet, seenKeys);
|
||||
[...otherKeys].forEach(k => {
|
||||
out[k] = obj[k];
|
||||
if (opts.fnUnhandledKey) opts.fnUnhandledKey(`${path}.${k}`);
|
||||
[...otherKeys].forEach(prop => {
|
||||
out[prop] = obj[prop];
|
||||
if (!opts.fnUnhandledKey) return;
|
||||
|
||||
const propMod = opts.isFoundryPrefixProps ? `foundry${prop.uppercaseFirst()}` : prop;
|
||||
const logPathNxt = `${logPath}.${prop}${propMod !== prop ? ` (${propMod})` : ""}`;
|
||||
opts.fnUnhandledKey(logPathNxt);
|
||||
});
|
||||
|
||||
return out;
|
||||
@@ -115,6 +295,22 @@ PropOrder._ArrayKey = class {
|
||||
this.order = opts.order;
|
||||
this.fnSort = opts.fnSort;
|
||||
}
|
||||
|
||||
static getRootKey (prop) {
|
||||
return new this(
|
||||
prop,
|
||||
{
|
||||
fnGetOrder: () => PropOrder._PROP_TO_LIST[prop],
|
||||
fnSort: getFnListSort(prop),
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
PropOrder._IgnoredKey = class {
|
||||
constructor (key) {
|
||||
this.key = key;
|
||||
}
|
||||
};
|
||||
|
||||
PropOrder._PROPS_FOUNDRY_DATA = [
|
||||
@@ -157,6 +353,10 @@ PropOrder._FOUNDRY_GENERIC = [
|
||||
"flags",
|
||||
"img",
|
||||
|
||||
new PropOrder._ObjectKey("subEntities", {
|
||||
fnGetOrder: () => PropOrder._ROOT,
|
||||
}),
|
||||
|
||||
"_merge",
|
||||
];
|
||||
PropOrder._FOUNDRY_GENERIC_FEATURE = [
|
||||
@@ -179,6 +379,10 @@ PropOrder._FOUNDRY_GENERIC_FEATURE = [
|
||||
fnGetOrder: () => PropOrder._ENTRY_DATA_OBJECT,
|
||||
}),
|
||||
|
||||
new PropOrder._ObjectKey("subEntities", {
|
||||
fnGetOrder: () => PropOrder._ROOT,
|
||||
}),
|
||||
|
||||
"_merge",
|
||||
];
|
||||
PropOrder._MONSTER = [
|
||||
@@ -743,6 +947,11 @@ PropOrder._FOUNDRY_CLASS = [
|
||||
|
||||
"source",
|
||||
|
||||
"system",
|
||||
"effects",
|
||||
"flags",
|
||||
"img",
|
||||
|
||||
"advancement",
|
||||
"chooseSystem",
|
||||
"isChooseSystemRenderEntries",
|
||||
@@ -786,6 +995,9 @@ PropOrder._SUBCLASS = [
|
||||
"preparedSpellsProgression",
|
||||
"cantripProgression",
|
||||
"spellsKnownProgression",
|
||||
"spellsKnownProgressionFixed",
|
||||
"spellsKnownProgressionFixedAllowLowerLevel",
|
||||
"spellsKnownProgressionFixedByLevel",
|
||||
|
||||
"additionalSpells",
|
||||
|
||||
@@ -830,6 +1042,11 @@ PropOrder._FOUNDRY_SUBCLASS = [
|
||||
"className",
|
||||
"classSource",
|
||||
|
||||
"system",
|
||||
"effects",
|
||||
"flags",
|
||||
"img",
|
||||
|
||||
"advancement",
|
||||
"chooseSystem",
|
||||
"isChooseSystemRenderEntries",
|
||||
@@ -947,7 +1164,9 @@ PropOrder._FOUNDRY_CLASS_FEATURE = [
|
||||
"actorDataMod",
|
||||
"actorTokenMod",
|
||||
|
||||
"subEntities",
|
||||
new PropOrder._ObjectKey("subEntities", {
|
||||
fnGetOrder: () => PropOrder._ROOT,
|
||||
}),
|
||||
];
|
||||
PropOrder._FOUNDRY_SUBCLASS_FEATURE = [
|
||||
"name",
|
||||
@@ -978,7 +1197,9 @@ PropOrder._FOUNDRY_SUBCLASS_FEATURE = [
|
||||
"actorDataMod",
|
||||
"actorTokenMod",
|
||||
|
||||
"subEntities",
|
||||
new PropOrder._ObjectKey("subEntities", {
|
||||
fnGetOrder: () => PropOrder._ROOT,
|
||||
}),
|
||||
];
|
||||
PropOrder._LANGUAGE = [
|
||||
"name",
|
||||
@@ -2143,4 +2364,164 @@ PropOrder._PROP_TO_LIST = {
|
||||
"foundryMap": PropOrder._FOUNDRY_MAP,
|
||||
};
|
||||
|
||||
PropOrder._ROOT = [
|
||||
"$schema",
|
||||
|
||||
new PropOrder._ObjectKey("_meta", {
|
||||
fnGetOrder: () => PropOrder._META,
|
||||
}),
|
||||
|
||||
// region Player options
|
||||
PropOrder._ArrayKey.getRootKey("class"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryClass"),
|
||||
PropOrder._ArrayKey.getRootKey("classFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("subclass"),
|
||||
PropOrder._ArrayKey.getRootKey("foundrySubclass"),
|
||||
PropOrder._ArrayKey.getRootKey("subclassFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("classFeature"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryClassFeature"),
|
||||
PropOrder._ArrayKey.getRootKey("subclassFeature"),
|
||||
PropOrder._ArrayKey.getRootKey("foundrySubclassFeature"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("optionalfeature"),
|
||||
PropOrder._ArrayKey.getRootKey("optionalfeatureFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryOptionalfeature"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("background"),
|
||||
PropOrder._ArrayKey.getRootKey("backgroundFeature"),
|
||||
PropOrder._ArrayKey.getRootKey("backgroundFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("race"),
|
||||
PropOrder._ArrayKey.getRootKey("subrace"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryRace"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryRaceFeature"),
|
||||
PropOrder._ArrayKey.getRootKey("raceFluff"),
|
||||
new PropOrder._IgnoredKey("raceFluffMeta"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("feat"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryFeat"),
|
||||
PropOrder._ArrayKey.getRootKey("featFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("reward"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryReward"),
|
||||
PropOrder._ArrayKey.getRootKey("rewardFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("charoption"),
|
||||
PropOrder._ArrayKey.getRootKey("charoptionFluff"),
|
||||
// endregion
|
||||
|
||||
// region General entities
|
||||
PropOrder._ArrayKey.getRootKey("spell"),
|
||||
PropOrder._ArrayKey.getRootKey("spellFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("foundrySpell"),
|
||||
PropOrder._ArrayKey.getRootKey("spellList"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("baseitem"),
|
||||
PropOrder._ArrayKey.getRootKey("item"),
|
||||
PropOrder._ArrayKey.getRootKey("itemGroup"),
|
||||
PropOrder._ArrayKey.getRootKey("magicvariant"),
|
||||
PropOrder._ArrayKey.getRootKey("itemFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryItem"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryMagicvariant"),
|
||||
|
||||
new PropOrder._IgnoredKey("itemProperty"),
|
||||
new PropOrder._IgnoredKey("reducedItemProperty"),
|
||||
new PropOrder._IgnoredKey("itemType"),
|
||||
new PropOrder._IgnoredKey("itemTypeAdditionalEntries"),
|
||||
new PropOrder._IgnoredKey("reducedItemType"),
|
||||
new PropOrder._IgnoredKey("itemEntry"),
|
||||
PropOrder._ArrayKey.getRootKey("itemMastery"),
|
||||
new PropOrder._IgnoredKey("linkedLootTables"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("deck"),
|
||||
PropOrder._ArrayKey.getRootKey("card"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("deity"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("language"),
|
||||
PropOrder._ArrayKey.getRootKey("languageScript"),
|
||||
PropOrder._ArrayKey.getRootKey("languageFluff"),
|
||||
// endregion
|
||||
|
||||
// region GM-specific
|
||||
PropOrder._ArrayKey.getRootKey("monster"),
|
||||
PropOrder._ArrayKey.getRootKey("monsterFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryMonster"),
|
||||
PropOrder._ArrayKey.getRootKey("legendaryGroup"),
|
||||
PropOrder._ArrayKey.getRootKey("monsterTemplate"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("object"),
|
||||
PropOrder._ArrayKey.getRootKey("objectFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("vehicle"),
|
||||
PropOrder._ArrayKey.getRootKey("vehicleUpgrade"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryVehicleUpgrade"),
|
||||
PropOrder._ArrayKey.getRootKey("vehicleFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("cult"),
|
||||
PropOrder._ArrayKey.getRootKey("boon"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("trap"),
|
||||
PropOrder._ArrayKey.getRootKey("trapFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("hazard"),
|
||||
PropOrder._ArrayKey.getRootKey("hazardFluff"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("encounter"),
|
||||
PropOrder._ArrayKey.getRootKey("name"),
|
||||
// endregion
|
||||
|
||||
// region Rules
|
||||
PropOrder._ArrayKey.getRootKey("variantrule"),
|
||||
PropOrder._ArrayKey.getRootKey("table"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("condition"),
|
||||
PropOrder._ArrayKey.getRootKey("conditionFluff"),
|
||||
PropOrder._ArrayKey.getRootKey("disease"),
|
||||
PropOrder._ArrayKey.getRootKey("status"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("action"),
|
||||
PropOrder._ArrayKey.getRootKey("foundryAction"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("skill"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("sense"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("citation"),
|
||||
|
||||
PropOrder._ArrayKey.getRootKey("adventure"),
|
||||
PropOrder._ArrayKey.getRootKey("adventureData"),
|
||||
PropOrder._ArrayKey.getRootKey("book"),
|
||||
PropOrder._ArrayKey.getRootKey("bookData"),
|
||||
// endregion
|
||||
|
||||
// region Other
|
||||
PropOrder._ArrayKey.getRootKey("recipe"),
|
||||
PropOrder._ArrayKey.getRootKey("recipeFluff"),
|
||||
// endregion
|
||||
|
||||
// region Legacy content
|
||||
PropOrder._ArrayKey.getRootKey("psionic"),
|
||||
new PropOrder._IgnoredKey("psionicDisciplineFocus"),
|
||||
new PropOrder._IgnoredKey("psionicDisciplineActive"),
|
||||
// endregion
|
||||
|
||||
// region Tooling
|
||||
PropOrder._ArrayKey.getRootKey("makebrewCreatureTrait"),
|
||||
PropOrder._ArrayKey.getRootKey("makebrewCreatureAction"),
|
||||
PropOrder._ArrayKey.getRootKey("monsterfeatures"),
|
||||
// endregion
|
||||
|
||||
// region Roll20-specific
|
||||
PropOrder._ArrayKey.getRootKey("roll20Spell"),
|
||||
// endregion
|
||||
|
||||
// region Non-brew data
|
||||
new PropOrder._IgnoredKey("blocklist"),
|
||||
// endregion
|
||||
|
||||
// region Misc ignored keys
|
||||
new PropOrder._IgnoredKey("data"),
|
||||
// endregion
|
||||
];
|
||||
|
||||
globalThis.PropOrder = PropOrder;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
class UtilsTableview {
|
||||
static _State = class {
|
||||
static _RenderState = class {
|
||||
constructor () {
|
||||
this.comp = null;
|
||||
this.rows = [];
|
||||
this.metasCbs = [];
|
||||
}
|
||||
@@ -17,63 +18,92 @@ class UtilsTableview {
|
||||
isEmpty: true,
|
||||
});
|
||||
|
||||
const state = new UtilsTableview._State();
|
||||
const rdState = new UtilsTableview._RenderState();
|
||||
|
||||
state.metasCbs = Object.values(colTransforms)
|
||||
.map((c, i) => {
|
||||
const $cb = $(`<input type="checkbox" class="mr-2" checked>`)
|
||||
.click(() => {
|
||||
const $eles = $modal.find(`[data-col="${i}"]`);
|
||||
$eles.toggleVe($cb.prop("checked"));
|
||||
});
|
||||
rdState.comp = BaseComponent.fromObject(
|
||||
Object.keys(colTransforms).mergeMap(k => ({[k]: true})),
|
||||
);
|
||||
|
||||
const $cbAll = $(`<input type="checkbox" title="Select All" checked>`)
|
||||
.on("click", () => {
|
||||
const val = $cbAll.prop("indeterminate") ? false : $cbAll.prop("checked");
|
||||
|
||||
rdState.comp._proxyAssignSimple(
|
||||
"state",
|
||||
Object.keys(colTransforms).mergeMap(k => ({[k]: val})),
|
||||
);
|
||||
});
|
||||
|
||||
rdState.metasCbs = Object.entries(colTransforms)
|
||||
.map(([prop, meta]) => {
|
||||
const $cb = ComponentUiUtil.$getCbBool(rdState.comp, prop);
|
||||
|
||||
const $wrp = $$`<label class="px-2 py-1 no-wrap ve-flex-inline-v-center">
|
||||
${$cb}
|
||||
<span>${c.name}</span>
|
||||
<span>${meta.name}</span>
|
||||
</label>`;
|
||||
|
||||
return {$wrp, $cb, name: c.name};
|
||||
return {$wrp, name: meta.name};
|
||||
});
|
||||
|
||||
Object.keys(colTransforms)
|
||||
.forEach((prop, i) => {
|
||||
rdState.comp._addHookBase(prop, () => {
|
||||
const propsSelected = Object.keys(colTransforms).map(prop => rdState.comp._state[prop]);
|
||||
if (propsSelected.every(Boolean)) $cbAll.prop("checked", true);
|
||||
else if (propsSelected.every(it => !it)) $cbAll.prop("checked", false);
|
||||
else $cbAll.prop("indeterminate", true).prop("checked", true);
|
||||
|
||||
const $eles = $modal.find(`[data-col="${i}"]`);
|
||||
$eles.toggleVe(rdState.comp._state[prop]);
|
||||
});
|
||||
});
|
||||
|
||||
const $btnCsv = $(`<button class="btn btn-primary">Download CSV</button>`).click(() => {
|
||||
DataUtil.userDownloadText(`${title}.csv`, this._getAsCsv({state}));
|
||||
DataUtil.userDownloadText(`${title}.csv`, this._getAsCsv({colTransforms, rdState}));
|
||||
});
|
||||
|
||||
const $btnCopy = $(`<button class="btn btn-primary">Copy CSV to Clipboard</button>`).click(async () => {
|
||||
await MiscUtil.pCopyTextToClipboard(this._getAsCsv({state}));
|
||||
await MiscUtil.pCopyTextToClipboard(this._getAsCsv({colTransforms, rdState}));
|
||||
JqueryUtil.showCopiedEffect($btnCopy);
|
||||
});
|
||||
|
||||
$$($modal)`<div class="split-v-center my-3">
|
||||
<div class="ve-flex-v-center ve-flex-wrap">${state.metasCbs.map(({$wrp}) => $wrp)}</div>
|
||||
const $wrpRows = $(`<div class="ve-overflow-y-auto w-100 h-100 ve-flex-col ve-overflow-x-auto"></div>`);
|
||||
|
||||
$$($modal)`<div class="ve-flex-v-center my-3">
|
||||
<label class="ve-flex-vh-center pl-2 pr-3 h-100">${$cbAll}</label>
|
||||
<div class="vr-2 ml-0 h-100"></div>
|
||||
<div class="ve-flex-v-center ve-flex-wrap w-100 min-w-0">${rdState.metasCbs.map(({$wrp}) => $wrp)}</div>
|
||||
<div class="vr-2 h-100"></div>
|
||||
<div class="btn-group no-shrink ve-flex-v-center ml-3">
|
||||
${$btnCsv}
|
||||
${$btnCopy}
|
||||
</div>
|
||||
</div>
|
||||
<hr class="hr-1">`;
|
||||
<hr class="hr-1">
|
||||
${$wrpRows}
|
||||
`;
|
||||
|
||||
const tableHtml = this._getTableHtml({state, entities, colTransforms, sorter});
|
||||
$modal.append(tableHtml);
|
||||
const tableHtml = this._getTableHtml({rdState, entities, colTransforms, sorter});
|
||||
$wrpRows.fastSetHtml(tableHtml);
|
||||
}
|
||||
|
||||
static _getAsCsv ({state}) {
|
||||
const headersActive = state.metasCbs.map(({$cb, name}, i) => {
|
||||
if (!$cb.prop("checked")) return null;
|
||||
return {name, ix: i};
|
||||
}).filter(Boolean);
|
||||
static _getAsCsv ({colTransforms, rdState}) {
|
||||
const headersActive = Object.entries(colTransforms)
|
||||
.map(([prop, meta], ix) => ({name: meta.name, ix, isSelected: rdState.comp._state[prop]}))
|
||||
.filter(({isSelected}) => isSelected);
|
||||
|
||||
const parser = new DOMParser();
|
||||
const rows = state.rows.map(row => headersActive.map(({ix}) => parser.parseFromString(`<div>${row[ix]}</div>`, "text/html").documentElement.textContent));
|
||||
const rows = rdState.rows.map(row => headersActive.map(({ix}) => parser.parseFromString(`<div>${row[ix]}</div>`, "text/html").documentElement.textContent));
|
||||
return DataUtil.getCsv(headersActive.map(({name}) => name), rows);
|
||||
}
|
||||
|
||||
static _getTableHtml ({state, entities, colTransforms, sorter}) {
|
||||
let stack = `<div class="ve-overflow-y-auto w-100 h-100 ve-flex-col ve-overflow-x-auto">
|
||||
<table class="w-100 table-striped stats stats--book stats--book-large min-w-100 w-initial">
|
||||
<thead>
|
||||
<tr>${Object.values(colTransforms).map((c, i) => `<th data-col="${i}" class="px-2" colspan="${c.flex || 1}">${c.name}</th>`).join("")}</tr>
|
||||
</thead>
|
||||
<tbody>`;
|
||||
static _getTableHtml ({rdState, entities, colTransforms, sorter}) {
|
||||
let stack = `<table class="w-100 table-striped stats stats--book stats--book-large min-w-100 w-initial">
|
||||
<thead>
|
||||
<tr>${Object.values(colTransforms).map((c, i) => `<th data-col="${i}" class="px-2" colspan="${c.flex || 1}">${c.name}</th>`).join("")}</tr>
|
||||
</thead>
|
||||
<tbody>`;
|
||||
|
||||
const listCopy = [...entities];
|
||||
if (sorter) listCopy.sort(sorter);
|
||||
@@ -86,13 +116,11 @@ class UtilsTableview {
|
||||
row.push(val);
|
||||
return `<td data-col="${i}" class="px-2" colspan="${c.flex || 1}">${val || ""}</td>`;
|
||||
}).join("");
|
||||
state.rows.push(row);
|
||||
rdState.rows.push(row);
|
||||
stack += `</tr>`;
|
||||
});
|
||||
|
||||
stack += `</tbody>
|
||||
</table>
|
||||
</div>`;
|
||||
stack += `</tbody></table>`;
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
1177
js/utils-ui.js
1177
js/utils-ui.js
File diff suppressed because it is too large
Load Diff
355
js/utils.js
355
js/utils.js
@@ -2,7 +2,7 @@
|
||||
|
||||
// in deployment, `IS_DEPLOYED = "<version number>";` should be set below.
|
||||
globalThis.IS_DEPLOYED = undefined;
|
||||
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.207.2"/* 5ETOOLS_VERSION__CLOSE */;
|
||||
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.208.0"/* 5ETOOLS_VERSION__CLOSE */;
|
||||
globalThis.DEPLOYED_IMG_ROOT = undefined;
|
||||
// for the roll20 script to set
|
||||
globalThis.IS_VTT = false;
|
||||
@@ -731,6 +731,108 @@ Math.seed = Math.seed || function (s) {
|
||||
};
|
||||
};
|
||||
|
||||
class TemplateUtil {
|
||||
static initJquery () {
|
||||
/**
|
||||
* Template strings which can contain jQuery objects.
|
||||
* Usage: $$`<div>Press this button: ${$btn}</div>`
|
||||
* or: $$($ele)`<div>Press this button: ${$btn}</div>`
|
||||
* @return {jQuery}
|
||||
*/
|
||||
globalThis.$$ = (parts, ...args) => {
|
||||
if (parts instanceof jQuery || parts instanceof Node) {
|
||||
return (...passed) => {
|
||||
const parts2 = [...passed[0]];
|
||||
const args2 = passed.slice(1);
|
||||
parts2[0] = `<div>${parts2[0]}`;
|
||||
parts2.last(`${parts2.last()}</div>`);
|
||||
|
||||
const eleParts = parts instanceof jQuery ? parts[0] : parts;
|
||||
const $temp = $$(parts2, ...args2);
|
||||
$temp.children().each((i, e) => eleParts.appendChild(e));
|
||||
return $(eleParts);
|
||||
};
|
||||
}
|
||||
|
||||
// Note that passing in a jQuery collection of multiple elements is not supported
|
||||
const partsNxt = parts instanceof jQuery ? parts[0] : parts;
|
||||
const argsNxt = args
|
||||
.map(arg => {
|
||||
if (arg instanceof Array) return arg.flatMap(argSub => argSub instanceof jQuery ? argSub.get() : argSub);
|
||||
return arg instanceof jQuery ? arg.get() : arg;
|
||||
});
|
||||
return $(ee(partsNxt, ...argsNxt));
|
||||
};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static initVanilla () {
|
||||
/**
|
||||
* Template strings which can contain DOM elements.
|
||||
* Usage: ee`<div>Press this button: ${btn}</div>`
|
||||
* or: ee(ele)`<div>Press this button: ${btn}</div>`
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
globalThis.ee = (parts, ...args) => {
|
||||
if (parts instanceof Node) {
|
||||
return (...passed) => {
|
||||
const parts2 = [...passed[0]];
|
||||
const args2 = passed.slice(1);
|
||||
parts2[0] = `<div>${parts2[0]}`;
|
||||
parts2.last(`${parts2.last()}</div>`);
|
||||
|
||||
const eleTmp = ee(parts2, ...args2);
|
||||
Array.from(eleTmp.childNodes).forEach(node => parts.appendChild(node));
|
||||
|
||||
return e_({ele: parts});
|
||||
};
|
||||
}
|
||||
|
||||
const eles = [];
|
||||
let ixArg = 0;
|
||||
|
||||
const raw = parts
|
||||
.reduce((html, p) => {
|
||||
const myIxArg = ixArg++;
|
||||
if (args[myIxArg] == null) return `${html}${p}`;
|
||||
if (args[myIxArg] instanceof Array) return `${html}${args[myIxArg].map(arg => TemplateUtil._ee_handleArg(eles, arg)).join("")}${p}`;
|
||||
else return `${html}${TemplateUtil._ee_handleArg(eles, args[myIxArg])}${p}`;
|
||||
});
|
||||
|
||||
const eleTmpTemplate = document.createElement("template");
|
||||
eleTmpTemplate.innerHTML = raw;
|
||||
const {content: eleTmp} = eleTmpTemplate;
|
||||
|
||||
// debugger
|
||||
|
||||
Array.from(eleTmp.querySelectorAll(`[data-r="true"]`))
|
||||
.forEach((node, i) => node.replaceWith(eles[i]));
|
||||
|
||||
const childNodes = Array.from(eleTmp.childNodes);
|
||||
childNodes.forEach(node => document.adoptNode(node));
|
||||
|
||||
// If the caller has passed in a single element, return it
|
||||
if (childNodes.length === 1) return e_({ele: childNodes[0]});
|
||||
|
||||
// If the caller has passed in multiple elements with no wrapper, return an array
|
||||
return childNodes
|
||||
.map(childNode => e_({ele: childNode}));
|
||||
};
|
||||
}
|
||||
|
||||
static _ee_handleArg (eles, arg) {
|
||||
if (arg instanceof Node) {
|
||||
eles.push(arg);
|
||||
return `<${arg.tagName} data-r="true"></${arg.tagName}>`;
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
globalThis.TemplateUtil = TemplateUtil;
|
||||
|
||||
globalThis.JqueryUtil = {
|
||||
_isEnhancementsInit: false,
|
||||
initEnhancements () {
|
||||
@@ -739,58 +841,8 @@ globalThis.JqueryUtil = {
|
||||
|
||||
JqueryUtil.addSelectors();
|
||||
|
||||
/**
|
||||
* Template strings which can contain jQuery objects.
|
||||
* Usage: $$`<div>Press this button: ${$btn}</div>`
|
||||
* @return jQuery
|
||||
*/
|
||||
window.$$ = function (parts, ...args) {
|
||||
if (parts instanceof jQuery || parts instanceof HTMLElement) {
|
||||
return (...passed) => {
|
||||
const parts2 = [...passed[0]];
|
||||
const args2 = passed.slice(1);
|
||||
parts2[0] = `<div>${parts2[0]}`;
|
||||
parts2.last(`${parts2.last()}</div>`);
|
||||
|
||||
const $temp = $$(parts2, ...args2);
|
||||
$temp.children().each((i, e) => $(e).appendTo(parts));
|
||||
return parts;
|
||||
};
|
||||
} else {
|
||||
const $eles = [];
|
||||
let ixArg = 0;
|
||||
|
||||
const handleArg = (arg) => {
|
||||
if (arg instanceof $) {
|
||||
$eles.push(arg);
|
||||
return `<${arg.tag()} data-r="true"></${arg.tag()}>`;
|
||||
} else if (arg instanceof HTMLElement) {
|
||||
return handleArg($(arg));
|
||||
} else return arg;
|
||||
};
|
||||
|
||||
const raw = parts.reduce((html, p) => {
|
||||
const myIxArg = ixArg++;
|
||||
if (args[myIxArg] == null) return `${html}${p}`;
|
||||
if (args[myIxArg] instanceof Array) return `${html}${args[myIxArg].map(arg => handleArg(arg)).join("")}${p}`;
|
||||
else return `${html}${handleArg(args[myIxArg])}${p}`;
|
||||
});
|
||||
const $res = $(raw);
|
||||
|
||||
if ($res.length === 1) {
|
||||
if ($res.attr("data-r") === "true") return $eles[0];
|
||||
else $res.find(`[data-r=true]`).replaceWith(i => $eles[i]);
|
||||
} else {
|
||||
// Handle case where user has passed in a bunch of elements with no outer wrapper
|
||||
const $tmp = $(`<div></div>`);
|
||||
$tmp.append($res);
|
||||
$tmp.find(`[data-r=true]`).replaceWith(i => $eles[i]);
|
||||
return $tmp.children();
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
};
|
||||
TemplateUtil.initVanilla();
|
||||
TemplateUtil.initJquery();
|
||||
|
||||
$.fn.extend({
|
||||
// avoid setting input type to "search" as it visually offsets the contents of the input
|
||||
@@ -1023,6 +1075,44 @@ globalThis.ElementUtil = {
|
||||
"disabled",
|
||||
]),
|
||||
|
||||
/**
|
||||
* @typedef {HTMLElement} HTMLElementModified
|
||||
* @extends {HTMLElement}
|
||||
*
|
||||
* @property {function(HTMLElement): HTMLElementModified} appends
|
||||
* @property {function(HTMLElement): HTMLElementModified} appendTo
|
||||
* @property {function(HTMLElement): HTMLElementModified} prependTo
|
||||
* @property {function(HTMLElement): HTMLElementModified} insertAfter
|
||||
*
|
||||
* @property {function(string): HTMLElementModified} addClass
|
||||
* @property {function(string): HTMLElementModified} removeClass
|
||||
* @property {function(string, ?boolean): HTMLElementModified} toggleClass
|
||||
*
|
||||
* @property {function(): HTMLElementModified} showVe
|
||||
* @property {function(): HTMLElementModified} hideVe
|
||||
* @property {function(?boolean): HTMLElementModified} toggleVe
|
||||
*
|
||||
* @property {function(): HTMLElementModified} empty
|
||||
* @property {function(): HTMLElementModified} detach
|
||||
*
|
||||
* @property {function(string, string): HTMLElementModified} attr
|
||||
* @property {function(*=): *} val
|
||||
*
|
||||
* @property {function(?string): (HTMLElementModified|string)} html
|
||||
* @property {function(?string): (HTMLElementModified|string)} txt
|
||||
*
|
||||
* @property {function(string): HTMLElementModified} tooltip
|
||||
* @property {function(): HTMLElementModified} disableSpellcheck
|
||||
*
|
||||
* @property {function(string, function): HTMLElementModified} onn
|
||||
* @property {function(function): HTMLElementModified} onClick
|
||||
* @property {function(function): HTMLElementModified} onContextmenu
|
||||
* @property {function(function): HTMLElementModified} onChange
|
||||
* @property {function(function): HTMLElementModified} onKeydown
|
||||
* @property {function(function): HTMLElementModified} onKeyup
|
||||
*
|
||||
* @return {HTMLElementModified}
|
||||
*/
|
||||
getOrModify ({
|
||||
tag,
|
||||
clazz,
|
||||
@@ -1110,7 +1200,7 @@ globalThis.ElementUtil = {
|
||||
ele.txt = ele.txt || ElementUtil._txt.bind(ele);
|
||||
ele.tooltip = ele.tooltip || ElementUtil._tooltip.bind(ele);
|
||||
ele.disableSpellcheck = ele.disableSpellcheck || ElementUtil._disableSpellcheck.bind(ele);
|
||||
ele.on = ele.on || ElementUtil._onX.bind(ele);
|
||||
ele.onn = ele.onn || ElementUtil._onX.bind(ele);
|
||||
ele.onClick = ele.onClick || ElementUtil._onX.bind(ele, "click");
|
||||
ele.onContextmenu = ele.onContextmenu || ElementUtil._onX.bind(ele, "contextmenu");
|
||||
ele.onChange = ele.onChange || ElementUtil._onX.bind(ele, "change");
|
||||
@@ -3664,13 +3754,28 @@ globalThis.DataUtil = {
|
||||
},
|
||||
|
||||
_mutAddProps (data) {
|
||||
if (data && typeof data === "object") {
|
||||
for (const k in data) {
|
||||
if (data[k] instanceof Array) {
|
||||
for (const it of data[k]) {
|
||||
if (typeof it !== "object") continue;
|
||||
it.__prop = k;
|
||||
}
|
||||
if (!data || typeof data !== "object") return;
|
||||
|
||||
for (const k in data) {
|
||||
if (!(data[k] instanceof Array)) continue;
|
||||
|
||||
for (const it of data[k]) {
|
||||
if (typeof it !== "object") continue;
|
||||
it.__prop = k;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_verifyMerged (data) {
|
||||
if (!data || typeof data !== "object") return;
|
||||
|
||||
for (const k in data) {
|
||||
if (!(data[k] instanceof Array)) continue;
|
||||
|
||||
for (const it of data[k]) {
|
||||
if (typeof it !== "object") continue;
|
||||
if (it._copy) {
|
||||
setTimeout(() => { throw new Error(`Unresolved "_copy" in entity: ${JSON.stringify(it)}`); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3706,7 +3811,10 @@ globalThis.DataUtil = {
|
||||
|
||||
async pDoMetaMerge (ident, data, options) {
|
||||
DataUtil._mutAddProps(data);
|
||||
DataUtil._merging[ident] = DataUtil._merging[ident] || DataUtil._pDoMetaMerge(ident, data, options);
|
||||
|
||||
const isFresh = !DataUtil._merging[ident];
|
||||
|
||||
DataUtil._merging[ident] ||= DataUtil._pDoMetaMerge(ident, data, options);
|
||||
await DataUtil._merging[ident];
|
||||
const out = DataUtil._merged[ident];
|
||||
|
||||
@@ -3717,6 +3825,8 @@ globalThis.DataUtil = {
|
||||
delete DataUtil._merged[ident];
|
||||
}
|
||||
|
||||
if (isFresh) DataUtil._verifyMerged(out);
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
@@ -3957,6 +4067,8 @@ globalThis.DataUtil = {
|
||||
return DataUtil._pLoadByMeta_pGetPrereleaseBrew(source);
|
||||
}
|
||||
case "race": {
|
||||
// FIXME(Future) this should really `loadRawJSON`, but this breaks existing brew.
|
||||
// Consider a large-scale migration in future.
|
||||
const data = await DataUtil.race.loadJSON({isAddBaseRaces: true});
|
||||
if (data[prop] && data[prop].some(it => it.source === source)) return data;
|
||||
return DataUtil._pLoadByMeta_pGetPrereleaseBrew(source);
|
||||
@@ -4093,8 +4205,7 @@ globalThis.DataUtil = {
|
||||
|
||||
if (!it) {
|
||||
if (options.isErrorOnMissing) {
|
||||
// In development/script mode, throw an exception
|
||||
if (!IS_DEPLOYED && !IS_VTT) throw new Error(`Could not find "${page}" entity "${entry._copy.name}" ("${entry._copy.source}") to copy in copier "${entry.name}" ("${entry.source}")`);
|
||||
throw new Error(`Could not find "${page}" entity "${entry._copy.name}" ("${entry._copy.source}") to copy in copier "${entry.name}" ("${entry.source}")`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -4113,9 +4224,10 @@ globalThis.DataUtil = {
|
||||
|
||||
_pMergeCopy_search (impl, page, entryList, entry, options) {
|
||||
const entryHash = UrlUtil.URL_TO_HASH_BUILDER[page](entry._copy);
|
||||
return entryList.find(it => {
|
||||
const hash = UrlUtil.URL_TO_HASH_BUILDER[page](it);
|
||||
impl._mergeCache[hash] = it;
|
||||
return entryList.find(ent => {
|
||||
const hash = UrlUtil.URL_TO_HASH_BUILDER[page](ent);
|
||||
// Avoid clobbering existing caches, as we assume "earlier = better"
|
||||
impl._mergeCache[hash] ||= ent;
|
||||
return hash === entryHash;
|
||||
});
|
||||
},
|
||||
@@ -4270,6 +4382,26 @@ globalThis.DataUtil = {
|
||||
} else throw new Error(`${msgPtFailed} One of "names" or "items" must be provided!`);
|
||||
}
|
||||
|
||||
static _doMod_renameArr ({copyTo, copyFrom, modInfo, msgPtFailed, prop, isThrow = true}) {
|
||||
this._doEnsureArray({obj: modInfo, prop: "renames"});
|
||||
|
||||
if (!copyTo[prop]) {
|
||||
if (isThrow) throw new Error(`${msgPtFailed} Could not find "${prop}" array`);
|
||||
return;
|
||||
}
|
||||
|
||||
modInfo.renames
|
||||
.forEach(rename => {
|
||||
const ent = copyTo[prop].find(ent => ent?.name === rename.rename);
|
||||
if (!ent) {
|
||||
if (isThrow) throw new Error(`${msgPtFailed} Could not find "${prop}" item with name "${rename.rename}" to rename`);
|
||||
return;
|
||||
}
|
||||
|
||||
ent.name = rename.with;
|
||||
});
|
||||
}
|
||||
|
||||
static _doMod_calculateProp ({copyTo, copyFrom, modInfo, msgPtFailed, prop}) {
|
||||
copyTo[prop] = copyTo[prop] || {};
|
||||
const toExec = modInfo.formula.replace(/<\$([^$]+)\$>/g, (...m) => {
|
||||
@@ -4576,7 +4708,7 @@ globalThis.DataUtil = {
|
||||
|
||||
static _doMod_setProp ({copyTo, copyFrom, modInfo, msgPtFailed, prop}) {
|
||||
const propPath = modInfo.prop.split(".");
|
||||
if (prop !== "*") propPath.unshift(prop);
|
||||
if (prop != null && prop !== "*") propPath.unshift(prop);
|
||||
MiscUtil.set(copyTo, ...propPath, MiscUtil.copyFast(modInfo.value));
|
||||
}
|
||||
|
||||
@@ -4599,6 +4731,7 @@ globalThis.DataUtil = {
|
||||
case "appendIfNotExistsArr": return this._doMod_appendIfNotExistsArr({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "insertArr": return this._doMod_insertArr({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "removeArr": return this._doMod_removeArr({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "renameArr": return this._doMod_renameArr({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "calculateProp": return this._doMod_calculateProp({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "scalarAddProp": return this._doMod_scalarAddProp({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
case "scalarMultProp": return this._doMod_scalarMultProp({copyTo, copyFrom, modInfo, msgPtFailed, prop});
|
||||
@@ -5535,19 +5668,17 @@ globalThis.DataUtil = {
|
||||
static _PAGE = UrlUtil.PG_RACES;
|
||||
static _FILENAME = "races.json";
|
||||
|
||||
static _loadCache = {};
|
||||
static _pIsLoadings = {};
|
||||
static _psLoadJson = {};
|
||||
|
||||
static async loadJSON ({isAddBaseRaces = false} = {}) {
|
||||
if (!DataUtil.race._pIsLoadings[isAddBaseRaces]) {
|
||||
DataUtil.race._pIsLoadings[isAddBaseRaces] = (async () => {
|
||||
DataUtil.race._loadCache[isAddBaseRaces] = DataUtil.race.getPostProcessedSiteJson(
|
||||
await this.loadRawJSON(),
|
||||
{isAddBaseRaces},
|
||||
);
|
||||
})();
|
||||
}
|
||||
await DataUtil.race._pIsLoadings[isAddBaseRaces];
|
||||
return DataUtil.race._loadCache[isAddBaseRaces];
|
||||
const cacheKey = `site-${isAddBaseRaces}`;
|
||||
DataUtil.race._psLoadJson[cacheKey] ||= (async () => {
|
||||
return DataUtil.race.getPostProcessedSiteJson(
|
||||
await this.loadRawJSON(),
|
||||
{isAddBaseRaces},
|
||||
);
|
||||
})();
|
||||
return DataUtil.race._psLoadJson[cacheKey];
|
||||
}
|
||||
|
||||
static getPostProcessedSiteJson (rawRaceData, {isAddBaseRaces = false} = {}) {
|
||||
@@ -5567,11 +5698,15 @@ globalThis.DataUtil = {
|
||||
}
|
||||
|
||||
static async loadPrerelease ({isAddBaseRaces = true} = {}) {
|
||||
return DataUtil.race._loadPrereleaseBrew({isAddBaseRaces, brewUtil: typeof PrereleaseUtil !== "undefined" ? PrereleaseUtil : null});
|
||||
const cacheKey = `prerelease-${isAddBaseRaces}`;
|
||||
this._psLoadJson[cacheKey] ||= DataUtil.race._loadPrereleaseBrew({isAddBaseRaces, brewUtil: typeof PrereleaseUtil !== "undefined" ? PrereleaseUtil : null});
|
||||
return this._psLoadJson[cacheKey];
|
||||
}
|
||||
|
||||
static async loadBrew ({isAddBaseRaces = true} = {}) {
|
||||
return DataUtil.race._loadPrereleaseBrew({isAddBaseRaces, brewUtil: typeof BrewUtil2 !== "undefined" ? BrewUtil2 : null});
|
||||
const cacheKey = `brew-${isAddBaseRaces}`;
|
||||
this._psLoadJson[cacheKey] ||= DataUtil.race._loadPrereleaseBrew({isAddBaseRaces, brewUtil: typeof BrewUtil2 !== "undefined" ? BrewUtil2 : null});
|
||||
return this._psLoadJson[cacheKey];
|
||||
}
|
||||
|
||||
static async _loadPrereleaseBrew ({isAddBaseRaces = true, brewUtil} = {}) {
|
||||
@@ -5653,60 +5788,22 @@ globalThis.DataUtil = {
|
||||
static _FILENAME = "recipes.json";
|
||||
|
||||
static async loadJSON () {
|
||||
const rawData = await super.loadJSON();
|
||||
return {recipe: await DataUtil.recipe.pGetPostProcessedRecipes(rawData.recipe)};
|
||||
}
|
||||
|
||||
static async pGetPostProcessedRecipes (recipes) {
|
||||
if (!recipes?.length) return;
|
||||
|
||||
recipes = MiscUtil.copyFast(recipes);
|
||||
|
||||
// Apply ingredient properties
|
||||
recipes.forEach(r => Renderer.recipe.populateFullIngredients(r));
|
||||
|
||||
const out = [];
|
||||
|
||||
// region Merge together main data and fluff, as we render the fluff in the main tab
|
||||
for (const r of recipes) {
|
||||
const fluff = await Renderer.utils.pGetFluff({
|
||||
entity: r,
|
||||
fluffProp: "recipeFluff",
|
||||
});
|
||||
|
||||
if (!fluff) {
|
||||
out.push(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
const cpyR = MiscUtil.copyFast(r);
|
||||
cpyR.fluff = MiscUtil.copyFast(fluff);
|
||||
delete cpyR.fluff.name;
|
||||
delete cpyR.fluff.source;
|
||||
out.push(cpyR);
|
||||
}
|
||||
//
|
||||
|
||||
return out;
|
||||
return DataUtil.recipe._pLoadJson = DataUtil.recipe._pLoadJson || (async () => {
|
||||
return {
|
||||
recipe: await DataLoader.pCacheAndGetAllSite("recipe"),
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
static async loadPrerelease () {
|
||||
return this._loadPrereleaseBrew({brewUtil: typeof PrereleaseUtil !== "undefined" ? PrereleaseUtil : null});
|
||||
return {
|
||||
recipe: await DataLoader.pCacheAndGetAllPrerelease("recipe"),
|
||||
};
|
||||
}
|
||||
|
||||
static async loadBrew () {
|
||||
return this._loadPrereleaseBrew({brewUtil: typeof BrewUtil2 !== "undefined" ? BrewUtil2 : null});
|
||||
}
|
||||
|
||||
static async _loadPrereleaseBrew ({brewUtil}) {
|
||||
if (!brewUtil) return {};
|
||||
|
||||
const brew = await brewUtil.pGetBrewProcessed();
|
||||
if (!brew?.recipe?.length) return brew;
|
||||
|
||||
return {
|
||||
...brew,
|
||||
recipe: await DataUtil.recipe.pGetPostProcessedRecipes(brew.recipe),
|
||||
recipe: await DataLoader.pCacheAndGetAllBrew("recipe"),
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user