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

208 lines
5.5 KiB
JavaScript

"use strict";
class Hist {
static hashChange ({isForceLoad, isBlankFilterLoad = false} = {}) {
if (Hist.isHistorySuppressed) {
Hist.setSuppressHistory(false);
return;
}
const [link, ...sub] = Hist.getHashParts();
if (link !== Hist.lastLoadedLink || sub.length === 0 || isForceLoad) {
Hist.lastLoadedLink = link;
if (link === HASH_BLANK) {
isBlankFilterLoad = true;
} else {
const listItem = Hist.getActiveListItem(link);
if (listItem == null) {
if (typeof pHandleUnknownHash === "function" && window.location.hash.length && Hist._lastUnknownLink !== link) {
Hist._lastUnknownLink = link;
pHandleUnknownHash(link, sub);
return;
} else {
Hist._freshLoad();
return;
}
}
const toLoad = listItem.ix;
if (toLoad === undefined) Hist._freshLoad();
else {
Hist.lastLoadedId = listItem.ix;
loadHash(listItem.ix);
document.title = `${listItem.name ? `${listItem.name} - ` : ""}5etools`;
}
}
}
if (typeof loadSubHash === "function" && (sub.length > 0 || isForceLoad)) loadSubHash(sub);
if (isBlankFilterLoad) Hist._freshLoad();
}
static init (initialLoadComplete) {
window.onhashchange = () => Hist.hashChange({isForceLoad: true});
if (window.location.hash.length) {
Hist.hashChange();
} else {
Hist._freshLoad();
}
if (initialLoadComplete) Hist.initialLoad = false;
}
/**
* Allows the hash to be modified without triggering a hashchange
* @param val
*/
static setSuppressHistory (val) {
Hist.isHistorySuppressed = val;
}
static _listPage = null;
static setListPage (listPage) { this._listPage = listPage; }
static getSelectedListItem () {
const [link] = Hist.getHashParts();
return Hist.getActiveListItem(link);
}
static getSelectedListElementWithLocation () {
const [link] = Hist.getHashParts();
return Hist.getActiveListItem(link, true);
}
static getHashParts () {
return Hist.util.getHashParts(window.location.hash);
}
static getActiveListItem (link, getIndex) {
const primaryLists = this._listPage.primaryLists;
if (primaryLists && primaryLists.length) {
for (let x = 0; x < primaryLists.length; ++x) {
const list = primaryLists[x];
const foundItemIx = list.items.findIndex(it => it.values.hash === link);
if (~foundItemIx) {
if (getIndex) return {item: list.items[foundItemIx], x: x, y: foundItemIx, list};
return list.items[foundItemIx];
}
}
}
}
static _freshLoad () {
// defer this, in case the list needs to filter first
setTimeout(() => {
const goTo = $("#listcontainer").find(".list a").attr("href");
if (goTo) {
const parts = location.hash.split(HASH_PART_SEP);
const fullHash = `${goTo}${parts.length > 1 ? `${HASH_PART_SEP}${parts.slice(1).join(HASH_PART_SEP)}` : ""}`;
location.replace(fullHash);
}
}, 1);
}
static cleanSetHash (toSet) {
window.location.hash = Hist.util.getCleanHash(toSet);
}
static getHashSource () {
const [link] = Hist.getHashParts();
// by convention, the source is the last hash segment
return link ? link.split(HASH_LIST_SEP).last() : null;
}
static getSubHash (key) {
return Hist.util.getSubHash(window.location.hash, key);
}
/**
* Sets a subhash with the key specified, overwriting any existing.
* @param key Subhash key.
* @param val Subhash value. Passing a nully object removes the k/v pair.
*/
static setSubhash (key, val) {
const nxtHash = Hist.util.setSubhash(window.location.hash, key, val);
Hist.cleanSetHash(nxtHash);
}
static setMainHash (hash) {
const subHashPart = Hist.util.getHashParts(window.location.hash, key, val).slice(1).join(HASH_PART_SEP);
Hist.cleanSetHash([hash, subHashPart].filter(Boolean).join(HASH_PART_SEP));
}
static replaceHistoryHash (hash) {
window.history.replaceState(
{},
document.title,
`${location.origin}${location.pathname}${hash ? `#${hash}` : ""}`,
);
}
}
Hist.lastLoadedLink = null;
Hist._lastUnknownLink = null;
Hist.lastLoadedId = null;
Hist.initialLoad = true;
Hist.isHistorySuppressed = false;
Hist.util = class {
static getCleanHash (hash) {
return hash.replace(/,+/g, ",").replace(/,$/, "").toLowerCase();
}
static _SYMS_NO_ENCODE = [/(,)/g, /(:)/g, /(=)/g];
static getHashParts (location, {isReturnEncoded = false} = {}) {
if (location[0] === "#") location = location.slice(1);
// Handle junk from external ads
if (location === "google_vignette") location = "";
if (isReturnEncoded) {
return location
.split(HASH_PART_SEP);
}
// region Normalize encoding
let pts = [location];
this._SYMS_NO_ENCODE.forEach(re => {
pts = pts.map(pt => pt.split(re)).flat();
});
pts = pts.map(pt => {
if (this._SYMS_NO_ENCODE.some(re => re.test(pt))) return pt;
return decodeURIComponent(pt).toUrlified();
});
location = pts.join("");
// endregion
return location
.split(HASH_PART_SEP);
}
static getSubHash (location, key) {
const [link, ...sub] = Hist.util.getHashParts(location);
const hKey = `${key}${HASH_SUB_KV_SEP}`;
const part = sub.find(it => it.startsWith(hKey));
if (part) return part.slice(hKey.length);
return null;
}
static setSubhash (location, key, val) {
if (key.endsWith(HASH_SUB_KV_SEP)) key = key.slice(0, -1);
const [link, ...sub] = Hist.util.getHashParts(location);
if (!link) return "";
const hKey = `${key}${HASH_SUB_KV_SEP}`;
const out = [link];
if (sub.length) sub.filter(it => !it.startsWith(hKey)).forEach(it => out.push(it));
if (val != null) out.push(`${hKey}${val}`);
return Hist.util.getCleanHash(out.join(HASH_PART_SEP));
}
};
globalThis.Hist = Hist;