BibTest.js: Difference between revisions
From Illustrations in German Translations of Mark Twain's Works
No edit summary |
No edit summary |
||
| Line 21: | Line 21: | ||
// Sammle alle Original-Taggamen aus den Einträgen | // Sammle alle Original-Taggamen aus den Einträgen | ||
const allTagsMap = new Map(); | const allTagsMap = new Map(); | ||
document.querySelectorAll('.bib-entry .tag').forEach(tagEl => { | document.querySelectorAll('.bib-entry .tag').forEach(tagEl => { | ||
const originalName = tagEl.textContent.trim(); | const originalName = tagEl.textContent.trim(); | ||
| Line 30: | Line 30: | ||
// Lösche alte Tags aus tagBar (aber nur einmal!) | // Lösche alte Tags aus tagBar (aber nur einmal!) | ||
if (tagBar.children.length === 0) { | if (tagBar.children.length === 0) { | ||
Array.from(allTagsMap.entries()) | Array.from(allTagsMap.entries()) | ||
.sort((a, b) => a[1].localeCompare(b[1])) | .sort((a, b) => a[1].localeCompare(b[1])) | ||
.forEach(([normalized, originalName]) => { | .forEach(([normalized, originalName]) => { | ||
const span = document.createElement('span'); | const span = document.createElement('span'); | ||
span.className = 'tag inactive'; | span.className = 'tag inactive'; | ||
span.textContent = originalName; | span.textContent = originalName; | ||
span.dataset.normalized = normalized; | span.dataset.normalized = normalized; | ||
span.onclick = () => toggleTag(originalName, span, normalized); | span.onclick = () => toggleTag(originalName, span, normalized); | ||
tagBar.appendChild(span); | tagBar.appendChild(span); | ||
| Line 43: | Line 42: | ||
} | } | ||
// Search Input Listener | // Search Input Listener | ||
if (searchInput && !searchInput.dataset.listenerSet) { | if (searchInput && !searchInput.dataset.listenerSet) { | ||
searchInput.addEventListener('input', (e) => { | searchInput.addEventListener('input', (e) => { | ||
| Line 52: | Line 51: | ||
} | } | ||
sortEntries(); | sortEntries(); | ||
} | } | ||
function hideEmptyAbstracts() { | function hideEmptyAbstracts() { | ||
document.querySelectorAll('.bib-entry | document.querySelectorAll('.bib-entry').forEach(entry => { | ||
const | const abstractDiv = entry.querySelector('.abstract'); | ||
const expandBtn = | const expandBtn = entry.querySelector('.expand-btn'); | ||
if (! | if (!abstractDiv || !expandBtn) return; | ||
const abstractText = p.textContent.trim(); | const p = abstractDiv.querySelector('p'); | ||
const abstractText = p ? p.textContent.trim() : ''; | |||
if (!abstractText || abstractText === 'No abstract available.') { | if (!abstractText || abstractText === 'No abstract available.') { | ||
expandBtn.style.display = 'none'; | |||
abstractDiv.style.display = 'none'; | abstractDiv.style.display = 'none'; | ||
} else { | } else { | ||
expandBtn.style.display = 'block'; | |||
abstractDiv.style.display = 'block'; | abstractDiv.style.display = 'block'; | ||
} | } | ||
| Line 81: | Line 75: | ||
function hideEmptyNotes() { | function hideEmptyNotes() { | ||
document.querySelectorAll('. | document.querySelectorAll('.expand-btn-notes').forEach(notesBtn => { | ||
const notesDiv = notesBtn.nextElementSibling; | |||
if (!notesDiv || !notesDiv.classList.contains('notes')) { | |||
console.warn('Notes Div nicht gefunden nach Button'); | |||
return; | |||
} | |||
const p = notesDiv.querySelector('p'); | const p = notesDiv.querySelector('p'); | ||
const | const notesText = p ? p.textContent.trim() : ''; | ||
console.log('Notes Text:', notesText); // Debug | |||
if (!notesText) { | if (!notesText) { | ||
notesBtn.style.display = 'none'; | |||
notesDiv.style.display = 'none'; | notesDiv.style.display = 'none'; | ||
} else { | } else { | ||
notesBtn.style.display = 'block'; | |||
notesDiv.style.display = 'block'; | notesDiv.style.display = 'block'; | ||
} | } | ||
| Line 141: | Line 135: | ||
const searchText = SEARCH_TERM; | const searchText = SEARCH_TERM; | ||
const title = entry.querySelector('h3')?.textContent || ''; | const title = entry.querySelector('h3')?.textContent || ''; | ||
if (title.toLowerCase().includes(searchText)) return true; | if (title.toLowerCase().includes(searchText)) return true; | ||
const tagElements = entry.querySelectorAll('.tag'); | const tagElements = entry.querySelectorAll('.tag'); | ||
for (let tag of tagElements) { | for (let tag of tagElements) { | ||
| Line 151: | Line 143: | ||
} | } | ||
const abstractDiv = entry.querySelector('.abstract'); | const abstractDiv = entry.querySelector('.abstract'); | ||
if (abstractDiv) { | if (abstractDiv) { | ||
| Line 158: | Line 149: | ||
} | } | ||
const notesDiv = entry.querySelector('.notes'); | const notesDiv = entry.querySelector('.notes'); | ||
if (notesDiv) { | if (notesDiv) { | ||
| Line 174: | Line 164: | ||
const entryTags = (entry.getAttribute('data-tags') || '').split(' ').filter(t => t); | const entryTags = (entry.getAttribute('data-tags') || '').split(' ').filter(t => t); | ||
let matchesTags = true; | let matchesTags = true; | ||
if (ACTIVE_TAGS.size > 0) { | if (ACTIVE_TAGS.size > 0) { | ||
| Line 182: | Line 171: | ||
} | } | ||
const matchesSearchTerm = matchesSearch(entry); | const matchesSearchTerm = matchesSearch(entry); | ||
entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none'; | entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none'; | ||
}); | }); | ||
| Line 193: | Line 180: | ||
document.addEventListener('click', function(e) { | document.addEventListener('click', function(e) { | ||
// Abstract Button | // Abstract Button | ||
if (e.target.classList.contains('expand-btn')) { | if (e.target.classList.contains('expand-btn') && !e.target.classList.contains('expand-btn-notes')) { | ||
const abstractDiv = e.target.nextElementSibling; | const abstractDiv = e.target.nextElementSibling; | ||
if (abstractDiv && abstractDiv.classList.contains('abstract')) { | if (abstractDiv && abstractDiv.classList.contains('abstract')) { | ||
| Line 203: | Line 190: | ||
} | } | ||
// Notes Button | // Notes Button - mit besserer Fehlerbehandlung | ||
if (e.target.classList.contains('expand-btn-notes')) { | if (e.target.classList.contains('expand-btn-notes')) { | ||
console.log('Notes Button geklickt'); | |||
const notesDiv = e.target.nextElementSibling; | const notesDiv = e.target.nextElementSibling; | ||
if (notesDiv | |||
if (!notesDiv) { | |||
console.error('Kein Element nach Notes Button gefunden'); | |||
return; | |||
} | } | ||
if (!notesDiv.classList.contains('notes')) { | |||
console.error('Nächstes Element ist kein .notes Div:', notesDiv); | |||
return; | |||
} | |||
notesDiv.classList.toggle('hidden'); | |||
e.target.textContent = notesDiv.classList.contains('hidden') | |||
? 'Show Notes' | |||
: 'Hide Notes'; | |||
} | } | ||
}); | }); | ||
| Line 222: | Line 219: | ||
} | } | ||
document.addEventListener('DOMContentLoaded', init); | document.addEventListener('DOMContentLoaded', init); | ||
})(); | })(); | ||
Revision as of 22:42, 21 May 2026
/**
* Bibliography Tag Filter, Sorting and Search
*/
(function() {
'use strict';
let ACTIVE_TAGS = new Set();
let SEARCH_TERM = '';
function init() {
const tagBar = document.getElementById('tagBar');
const bibliography = document.getElementById('listView');
const searchInput = document.getElementById('bibSearch');
if (!tagBar || !bibliography) return;
// Verstecke leere Abstract- und Notes-Buttons
hideEmptyAbstracts();
hideEmptyNotes();
// Sammle alle Original-Taggamen aus den Einträgen
const allTagsMap = new Map();
document.querySelectorAll('.bib-entry .tag').forEach(tagEl => {
const originalName = tagEl.textContent.trim();
const normalized = normalizeTag(originalName);
allTagsMap.set(normalized, originalName);
});
// Lösche alte Tags aus tagBar (aber nur einmal!)
if (tagBar.children.length === 0) {
Array.from(allTagsMap.entries())
.sort((a, b) => a[1].localeCompare(b[1]))
.forEach(([normalized, originalName]) => {
const span = document.createElement('span');
span.className = 'tag inactive';
span.textContent = originalName;
span.dataset.normalized = normalized;
span.onclick = () => toggleTag(originalName, span, normalized);
tagBar.appendChild(span);
});
}
// Search Input Listener
if (searchInput && !searchInput.dataset.listenerSet) {
searchInput.addEventListener('input', (e) => {
SEARCH_TERM = e.target.value.toLowerCase();
filterEntries();
});
searchInput.dataset.listenerSet = 'true';
}
sortEntries();
}
function hideEmptyAbstracts() {
document.querySelectorAll('.bib-entry').forEach(entry => {
const abstractDiv = entry.querySelector('.abstract');
const expandBtn = entry.querySelector('.expand-btn');
if (!abstractDiv || !expandBtn) return;
const p = abstractDiv.querySelector('p');
const abstractText = p ? p.textContent.trim() : '';
if (!abstractText || abstractText === 'No abstract available.') {
expandBtn.style.display = 'none';
abstractDiv.style.display = 'none';
} else {
expandBtn.style.display = 'block';
abstractDiv.style.display = 'block';
}
});
}
function hideEmptyNotes() {
document.querySelectorAll('.expand-btn-notes').forEach(notesBtn => {
const notesDiv = notesBtn.nextElementSibling;
if (!notesDiv || !notesDiv.classList.contains('notes')) {
console.warn('Notes Div nicht gefunden nach Button');
return;
}
const p = notesDiv.querySelector('p');
const notesText = p ? p.textContent.trim() : '';
console.log('Notes Text:', notesText); // Debug
if (!notesText) {
notesBtn.style.display = 'none';
notesDiv.style.display = 'none';
} else {
notesBtn.style.display = 'block';
notesDiv.style.display = 'block';
}
});
}
function toggleTag(tagName, element, normalized) {
if (ACTIVE_TAGS.has(normalized)) {
ACTIVE_TAGS.delete(normalized);
element.classList.remove('active');
element.classList.add('inactive');
} else {
ACTIVE_TAGS.add(normalized);
element.classList.add('active');
element.classList.remove('inactive');
}
filterEntries();
}
function sortEntries() {
const container = document.getElementById('listView');
if (!container) return;
const entries = Array.from(container.querySelectorAll('.bib-entry'));
entries.sort((a, b) => {
const titleA = a.querySelector('h3')?.textContent || '';
const titleB = b.querySelector('h3')?.textContent || '';
return titleA.localeCompare(titleB);
});
entries.forEach(entry => container.appendChild(entry));
}
function normalizeTag(tag) {
return tag.toLowerCase().replace(/\s+/g, '_').replace(/,/g, '').replace(/\./g, '').replace(/'/g, '').replace(/"/g, '');
}
function matchesSearch(entry) {
if (!SEARCH_TERM) return true;
const searchText = SEARCH_TERM;
const title = entry.querySelector('h3')?.textContent || '';
if (title.toLowerCase().includes(searchText)) return true;
const tagElements = entry.querySelectorAll('.tag');
for (let tag of tagElements) {
if (tag.textContent.toLowerCase().includes(searchText)) return true;
}
const abstractDiv = entry.querySelector('.abstract');
if (abstractDiv) {
const abstractText = abstractDiv.textContent || '';
if (abstractText.toLowerCase().includes(searchText)) return true;
}
const notesDiv = entry.querySelector('.notes');
if (notesDiv) {
const notesText = notesDiv.textContent || '';
if (notesText.toLowerCase().includes(searchText)) return true;
}
return false;
}
function filterEntries() {
const entries = document.querySelectorAll('.bib-entry');
entries.forEach(entry => {
const entryTags = (entry.getAttribute('data-tags') || '').split(' ').filter(t => t);
let matchesTags = true;
if (ACTIVE_TAGS.size > 0) {
matchesTags = Array.from(ACTIVE_TAGS).every(activeTag => {
return entryTags.includes(activeTag);
});
}
const matchesSearchTerm = matchesSearch(entry);
entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none';
});
}
// Abstract- und Notes-Button Toggle
document.addEventListener('click', function(e) {
// Abstract Button
if (e.target.classList.contains('expand-btn') && !e.target.classList.contains('expand-btn-notes')) {
const abstractDiv = e.target.nextElementSibling;
if (abstractDiv && abstractDiv.classList.contains('abstract')) {
abstractDiv.classList.toggle('hidden');
e.target.textContent = abstractDiv.classList.contains('hidden')
? 'Show Abstract'
: 'Hide Abstract';
}
}
// Notes Button - mit besserer Fehlerbehandlung
if (e.target.classList.contains('expand-btn-notes')) {
console.log('Notes Button geklickt');
const notesDiv = e.target.nextElementSibling;
if (!notesDiv) {
console.error('Kein Element nach Notes Button gefunden');
return;
}
if (!notesDiv.classList.contains('notes')) {
console.error('Nächstes Element ist kein .notes Div:', notesDiv);
return;
}
notesDiv.classList.toggle('hidden');
e.target.textContent = notesDiv.classList.contains('hidden')
? 'Show Notes'
: 'Hide Notes';
}
});
// Starte wenn DOM bereit
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
document.addEventListener('DOMContentLoaded', init);
})();