BibTest.js: Difference between revisions
From Illustrations in German Translations of Mark Twain's Works
No edit summary |
No edit summary |
||
| (6 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
* Bibliography Tag Filter, Sorting and Search | * Bibliography Tag Filter, Sorting and Search | ||
*/ | */ | ||
function updateCounter() { | |||
const entries = document.querySelectorAll('.bib-entry'); | |||
const visible = Array.from(entries).filter(entry => entry.style.display !== 'none').length; | |||
const counter = document.getElementById('bibCounter'); | |||
if (counter) { | |||
counter.textContent = `${visible} of ${entries.length} sources shown`; | |||
} | |||
} | |||
(function() { | (function() { | ||
'use strict'; | 'use strict'; | ||
| Line 37: | Line 45: | ||
// Sonderfarbe für Twain-Werke | // Sonderfarbe für Twain-Werke | ||
const orangeTags = [ | |||
'a connecticut yankee in king arthur\'s court', | |||
'adventures of huckleberry finn', | |||
'pudd\'nhead wilson', | |||
'roughing it', | |||
'the adventures of tom sawyer', | |||
'the innocents abroad', | |||
]; | 'a tramp abroad' | ||
]; | |||
if (orangeTags.includes(originalName.toLowerCase())) { | |||
span.classList.add('twain-work'); | |||
} | |||
// Sonderfarbe für Illustratoren | |||
const illustratorTags = [ | const illustratorTags = [ | ||
'kemble, edward w.', | 'kemble, edward w.', | ||
'senior, frank m.', | 'senior, frank m.', | ||
'warren, calvin h.', | 'warren, calvin h.', | ||
'williams, | 'williams, true w.', | ||
'brown, walter f.', | |||
'beard, daniel carter' | |||
]; | ]; | ||
if (illustratorTags.includes(originalName.toLowerCase())) { | |||
span.classList.add('illustrator-tag'); | |||
} | |||
span.onclick = () => toggleTag(originalName, span, normalized); | span.onclick = () => toggleTag(originalName, span, normalized); | ||
| Line 61: | Line 77: | ||
}); | }); | ||
} | } | ||
// Info-Legende für Tag-Farben | |||
if (!document.getElementById('tagLegend')) { | |||
const legend = document.createElement('span'); | |||
legend.id = 'tagLegend'; | |||
legend.innerHTML = ` | |||
<span class="info-icon">i</span> | |||
<div class="legend-box"> | |||
<div><span class="legend-color twain"></span> Twain's Works</div> | |||
<div><span class="legend-color illustrator"></span> Illustrators</div> | |||
<div><span class="legend-color general"></span> General Tags</div> | |||
</div> | |||
`; | |||
tagBar.appendChild(legend); | |||
} | |||
// Search Input Listener | // Search Input Listener | ||
if (searchInput && !searchInput.dataset.listenerSet) { | if (searchInput && !searchInput.dataset.listenerSet) { | ||
| Line 75: | Line 106: | ||
removeEmptyAbstractButtons(); | removeEmptyAbstractButtons(); | ||
| Line 257: | Line 286: | ||
entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none'; | entry.style.display = (matchesTags && matchesSearchTerm) ? 'block' : 'none'; | ||
}); | }); | ||
updateCounter(); | |||
} | } | ||
| Line 268: | Line 298: | ||
document.addEventListener('DOMContentLoaded', init); | document.addEventListener('DOMContentLoaded', init); | ||
})(); | })(); | ||
updateCounter(); | |||
Latest revision as of 00:12, 17 July 2026
/**
* Bibliography Tag Filter, Sorting and Search
*/
function updateCounter() {
const entries = document.querySelectorAll('.bib-entry');
const visible = Array.from(entries).filter(entry => entry.style.display !== 'none').length;
const counter = document.getElementById('bibCounter');
if (counter) {
counter.textContent = `${visible} of ${entries.length} sources shown`;
}
}
(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;
// Sammle alle Original-Tagnamen 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;
// Sonderfarbe für Twain-Werke
const orangeTags = [
'a connecticut yankee in king arthur\'s court',
'adventures of huckleberry finn',
'pudd\'nhead wilson',
'roughing it',
'the adventures of tom sawyer',
'the innocents abroad',
'a tramp abroad'
];
if (orangeTags.includes(originalName.toLowerCase())) {
span.classList.add('twain-work');
}
// Sonderfarbe für Illustratoren
const illustratorTags = [
'kemble, edward w.',
'senior, frank m.',
'warren, calvin h.',
'williams, true w.',
'brown, walter f.',
'beard, daniel carter'
];
if (illustratorTags.includes(originalName.toLowerCase())) {
span.classList.add('illustrator-tag');
}
span.onclick = () => toggleTag(originalName, span, normalized);
tagBar.appendChild(span);
});
}
// Info-Legende für Tag-Farben
if (!document.getElementById('tagLegend')) {
const legend = document.createElement('span');
legend.id = 'tagLegend';
legend.innerHTML = `
<span class="info-icon">i</span>
<div class="legend-box">
<div><span class="legend-color twain"></span> Twain's Works</div>
<div><span class="legend-color illustrator"></span> Illustrators</div>
<div><span class="legend-color general"></span> General Tags</div>
</div>
`;
tagBar.appendChild(legend);
}
// Search Input Listener
if (searchInput && !searchInput.dataset.listenerSet) {
searchInput.addEventListener('input', (e) => {
SEARCH_TERM = e.target.value.toLowerCase();
filterEntries();
});
searchInput.dataset.listenerSet = 'true';
}
sortEntries();
removeEmptyAbstractButtons();
removeEmptyNotesButtons();
collapseAbstractsInitially();
collapseNotesInitially();
setupClickHandlers();
}
function removeEmptyAbstractButtons() {
document.querySelectorAll('.bib-entry').forEach(entry => {
const abstractDiv = entry.querySelector('.abstract');
const button = entry.querySelector('.expand-btn');
if (!abstractDiv || !button) return;
const text = abstractDiv.textContent.trim();
// Nur prüfen ob leer bzw. Platzhaltertext
if (
text === '' ||
text === 'No abstract available.'
) {
button.remove();
abstractDiv.remove();
}
});
}
function collapseAbstractsInitially() {
document.querySelectorAll('.abstract').forEach(el => {
el.classList.add('hidden');
el.style.display = ''; // entfernt evtl. inline overrides
});
}
function removeEmptyNotesButtons() {
document.querySelectorAll('.bib-entry').forEach(entry => {
const notesDiv = entry.querySelector('.notes');
const button = entry.querySelector('.expand-btn-notes');
if (!notesDiv || !button) return;
const text = notesDiv.textContent.trim();
if (text === '') {
button.remove();
notesDiv.remove();
}
});
}
function collapseNotesInitially() {
document.querySelectorAll('.notes').forEach(notesDiv => {
notesDiv.classList.add('hidden');
});
}
function setupClickHandlers() {
document.removeEventListener('click', handleClicks);
document.addEventListener('click', handleClicks);
}
function handleClicks(e) {
// =========================
// ABSTRACT TOGGLE
// =========================
if (e.target.classList.contains('expand-btn') &&
!e.target.classList.contains('expand-btn-notes')) {
const entry = e.target.closest('.bib-entry');
const abstractDiv = entry?.querySelector('.abstract');
if (!abstractDiv) return;
const isHidden = abstractDiv.classList.toggle('hidden');
e.target.textContent = isHidden
? 'Show Abstract'
: 'Hide Abstract';
}
// =========================
// NOTES TOGGLE
// =========================
if (e.target.classList.contains('expand-btn-notes')) {
const entry = e.target.closest('.bib-entry');
const notesDiv = entry?.querySelector('.notes');
if (!notesDiv) return;
const isHidden = notesDiv.classList.toggle('hidden');
e.target.textContent = isHidden
? 'Show Notes'
: 'Hide Notes';
}
}
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';
});
updateCounter();
}
// Starte wenn DOM bereit
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
document.addEventListener('DOMContentLoaded', init);
})();
updateCounter();