Single person page + reihen list

This commit is contained in:
Simon Martens
2025-02-23 19:27:26 +01:00
parent d8a01bfffb
commit 2ef3eda244
24 changed files with 802 additions and 133 deletions

View File

@@ -13,6 +13,7 @@ const FILTER_LIST_SEARCHABLE = "filter-list-searchable";
const SCROLL_BUTTON_ELEMENT = "scroll-button";
const TOOLTIP_ELEMENT = "tool-tip";
const ABBREV_TOOLTIPS_ELEMENT = "abbrev-tooltips";
class XSLTParseProcess {
#processors;
@@ -421,12 +422,15 @@ class ScrollButton extends HTMLElement {
class ToolTip extends HTMLElement {
static get observedAttributes() {
return ["position"];
return ["position", "timeout"];
}
constructor() {
super();
this._tooltipBox = null;
this._timeout = 200;
this._hideTimeout = null;
this._hiddenTimeout = null;
}
connectedCallback() {
@@ -477,9 +481,14 @@ class ToolTip extends HTMLElement {
if (name === "position" && this._tooltipBox) {
this._updatePosition();
}
if (name === "timeout" && newValue) {
this._timeout = parseInt(newValue) || 200;
}
}
_showTooltip() {
clearTimeout(this._hideTimeout);
clearTimeout(this._hiddenTimeout);
this._tooltipBox.classList.remove("hidden");
setTimeout(() => {
this._tooltipBox.classList.remove("opacity-0");
@@ -488,13 +497,13 @@ class ToolTip extends HTMLElement {
}
_hideTooltip() {
setTimeout(() => {
this._hideTimeout = setTimeout(() => {
this._tooltipBox.classList.remove("opacity-100");
this._tooltipBox.classList.add("opacity-0");
setTimeout(() => {
this._hiddenTimeout = setTimeout(() => {
this._tooltipBox.classList.add("hidden");
}, 200);
}, 100);
}, this._timeout + 100);
}, this._timeout);
}
_updatePosition() {
@@ -557,8 +566,181 @@ class ToolTip extends HTMLElement {
}
}
class AbbreviationTooltips extends HTMLElement {
static get observedAttributes() {
return ["data-text", "data-abbrevmap"];
}
static get defaultAbbrevMap() {
return {
"#": "Hinweis auf weitere Informationen in der Anmerkung.",
$: "vermutlich",
"+++": "Inhalte aus mehreren Almanachen interpoliert",
B: "Blatt",
BB: "Blätter",
C: "Corrigenda",
Diagr: "Diagramm",
G: "Graphik",
"G-Verz": "Verzeichnis der Kupfer u. ä.",
GG: "Graphiken",
Hrsg: "Herausgeber",
"I-Verz": "Inhaltsverzeichnis",
Kal: "Kalendarium",
Kr: "Karte",
MusB: "Musikbeigabe",
MusBB: "Musikbeigaben",
S: "Seite",
SS: "Seiten",
Sp: "Spiegel",
T: "Titel",
TG: "Titelgraphik, Titelportrait etc",
"TG r": "Titelgraphik, Titelportrait etc recto",
"TG v": "Titelgraphik, Titelportrait etc verso",
Tab: "Tabelle",
UG: "Umschlaggraphik",
"UG r": "Umschlaggraphik recto",
"UG v": "Umschlaggraphik verso",
VB: "Vorsatzblatt",
Vf: "Verfasser",
VrlgM: "Verlagsmitteilung",
Vrwrt: "Vorwort",
ar: "arabische Paginierung",
ar1: "erste arabische Paginierung",
ar2: "zweite arabische Paginierung",
ar3: "dritte arabische Paginierung",
ar4: "vierte arabische Paginierung",
ar5: "fünfte arabische Paginierung",
ar6: "sechste arabische Paginierung",
ar7: "siebte arabische Paginierung",
gA: "graphische Anleitung",
gT: "graphischer Titel",
gTzA: "graphische Tanzanleitung",
nT: "Nachtitel",
röm: "römische Paginierung",
röm1: "erste römische Paginierung",
röm2: "zweite römische Paginierung",
röm3: "dritte römische Paginierung",
röm4: "vierte römische Paginierung",
röm5: "fünfte römische Paginierung",
röm6: "sechste römische Paginierung",
röm7: "siebte römische Paginierung",
vT: "Vortitel",
zT: "Zwischentitel",
"§§": "Hinweis auf Mängel im Almanach (Beschädigungen, fehlende Graphiken, unvollständige Sammlungen etc) in der Anmerkung",
};
}
constructor() {
super();
this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap;
}
connectedCallback() {
this.render();
}
attributeChangedCallback(name, oldVal, newVal) {
if (oldVal !== newVal) {
if (name === "data-abbrevmap") {
this._parseAndSetAbbrevMap(newVal);
}
this.render();
}
}
_parseAndSetAbbrevMap(jsonStr) {
if (!jsonStr) {
this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap;
return;
}
try {
this._abbrevMap = JSON.parse(jsonStr);
} catch {
this._abbrevMap = AbbreviationTooltips.defaultAbbrevMap;
}
}
setAbbrevMap(map) {
if (typeof map === "object" && map !== null) {
this._abbrevMap = map;
this.render();
}
}
get text() {
return this.getAttribute("data-text") || "";
}
set text(value) {
this.setAttribute("data-text", value);
}
render() {
this.innerHTML = this.transformText(this.text, this._abbrevMap);
}
transformText(text, abbrevMap) {
let result = "";
let i = 0;
while (i < text.length) {
// Only match if at start of text or preceded by a boundary character
if (i > 0 && !this.isSpaceOrPunct(text[i - 1])) {
result += text[i];
i++;
continue;
}
const matchObj = this.findLongestAbbrevAt(text, i, abbrevMap);
if (matchObj) {
const { match, meaning } = matchObj;
result += `
<tool-tip position="top" class="!inline" timeout="300">
<div class="data-tip p-2 text-sm text-white bg-gray-700 rounded shadow">
${meaning}
</div>
<span class="cursor-help text-blue-900 hover:text-slate-800">
${match}
</span>
</tool-tip>
`;
i += match.length;
} else {
result += text[i];
i++;
}
}
return result;
}
findLongestAbbrevAt(text, i, abbrevMap) {
let bestKey = null;
let bestLength = 0;
for (const key of Object.keys(abbrevMap)) {
if (text.startsWith(key, i)) {
if (key.length > bestLength) {
bestKey = key;
bestLength = key.length;
}
}
}
if (bestKey) {
return { match: bestKey, meaning: abbrevMap[bestKey] };
}
return null;
}
isSpaceOrPunct(ch) {
// Adjust if you want a different set of punctuation recognized
return /\s|[.,;:!?]/.test(ch);
}
}
customElements.define(ABBREV_TOOLTIPS_ELEMENT, AbbreviationTooltips);
customElements.define(FILTER_LIST_ELEMENT, FilterList);
customElements.define(SCROLL_BUTTON_ELEMENT, ScrollButton);
customElements.define(TOOLTIP_ELEMENT, ToolTip);
export { XSLTParseProcess, FilterList, ScrollButton };
export { XSLTParseProcess, FilterList, ScrollButton, AbbreviationTooltips };

View File

@@ -312,4 +312,19 @@
#personalphabet a.inactive {
@apply !text-gray-400;
}
#entrydata .fieldlabel {
@apply font-bold text-base font-sans whitespace-nowrap w-60 grow-0 shrink-0 pt-0.5;
}
#entrydata .fieldvalue {
@apply font-serif text-left grow align-top max-w-[60ch];
}
#entrydata .entryrow {
@apply flex flex-row gap-x-3.5 items-start py-0.5 px-4;
}
#entrydata {
}
}